CompileTimeWeaver.Fody 3.1.7

Compile time IL weaver for AOP implementation.

Install-Package CompileTimeWeaver.Fody -Version 3.1.7
dotnet add package CompileTimeWeaver.Fody --version 3.1.7
paket add CompileTimeWeaver.Fody --version 3.1.7
The NuGet Team does not provide support for this client. Please contact its maintainers for support.

.Net Platforms

  • Framework 4.6.1
  • NetStandard 2.0

Compile time IL rewriting tool for AOP implementation

Different from runtime interception with dynamic proxy, this tool rewrites assembly at VisualStudio.Net build time, so that your code get these achievements that dynamic proxy based enhancement cannot give:

  • Much better performance, no dynamic proxy, no thread block or reflection at run time.
  • Directly instantiate your weaved classes with new operator
  • Weave virtual methods/properties
  • Weave static methods/properties
  • Weave extension methods
  • Weave constructors

Advice Based Programming Model

Start with version 2, this tool support advice based programming model. Advice based programming model has these superiorities comparing to the old decorator based programming model in version 1:

  • Easy to intercept async method without thread blocking
  • Simple to control the flow and add "before", "after", "around" and "exception" advises
  • Allow to advise methods with parameters of reference type, value type and generic type, ref parameters and out parameters are allowed, too.

Your Code

public class MyAdvice : AdviceAttribute
{
    public override object Advise(IInvocation invocation)
    {
        // do something before target method is Called
        // ...
        Trace.WriteLine("Entering " + invocation.Method.Name);

        try
        {
            return invocation.Proceed();	// call the next advice in the "chain" of advice pipeline, or call target method
        }
        catch (Exception e)
        {
            // do something when target method throws exception
            // ...
            Trace.WriteLine("MyAdvice catches an exception: " + e.Message);
            throw;
        }
        finally
        {
            // do something after target method is Called
            // ...
            Trace.WriteLine("Leaving " + invocation.Method.Name);
        }
    }

    public override async Task<object> AdviseAsync(IInvocation invocation)
    {
        // do something before target method is Called
        // ...
        Trace.WriteLine("Entering async " + invocation.Method.Name);

        try
        {
            return await invocation.ProceedAsync().ConfigureAwait(false);	// asynchronously call the next advice in advice pipeline, or call target method
        }
        catch (Exception e)
        {
            // do something when target method throws exception
            // ...
            Trace.WriteLine("MyAdvice catches an exception: " + e.Message);
            throw;
        }
        finally
        {
            // do something after target method is Called
            // ...
            Trace.WriteLine("Leaving async " + invocation.Method.Name);
        }
    }
}

[MyAdvice]
public class MyClass
{
	public int Add(int x, int y)
	{
		return x + y;
	}

	public Task<int> AddAsync(int x, int y)
	{
		await Task.Dely(1000).ConfigureAwait(false);
		return x + y;
	}
}

The first time when you compile MyClass class, FodyWeavers.xml and FodyWeavers.xsd are generated if they do not exist yet. FodyWeavers.xml content likes this below:

<?xml version="1.0" encoding="utf-8"?>
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
  <CompileTimeWeaver />
</Weavers>

If (1) your MyClass and MyAdvice are in different assemblies and (2) your target platform is netstandard, you need
to manually add the full name of MyAdvice class into AdviceAttributes property of CompileTimeWeaver section in FodyWeavers.xml file
as below (suppose the namespace of MyAdvice is Advices here):

  <CompileTimeWeaver AdviceAttributes="Advices.MyAdvice" />

To add more advice classes into AdviceAttributes property, seperate them with '|' delimitor, for example: AdviceAttributes="Advices.MyAdvice1|Advices.MyAdvice2".

You do not have to change this file if your target is .net Framework or MyClass and MyAdvice are in same assembly.

Notes:

  • When multiple advices are applied to a method, the advices are invoked as a pipe line, the Advise() or AdviseAsync() of the first advice is called first.
  • When an advice is applied to class level, it is identical to this advice is added on each constructor and each method.
  • Class level advices appears before all constructor/method level advices
  • Each advice is assigned an Order, it is the sequence number of the appearance in the type group.
  • Each advice on a recursive method is invoked only when the method was entered at the very first time, re-entrances don't invoke the advice again, for performance reason.

.Net Platforms

  • Framework 4.6.1
  • NetStandard 2.0

Compile time IL rewriting tool for AOP implementation

Different from runtime interception with dynamic proxy, this tool rewrites assembly at VisualStudio.Net build time, so that your code get these achievements that dynamic proxy based enhancement cannot give:

  • Much better performance, no dynamic proxy, no thread block or reflection at run time.
  • Directly instantiate your weaved classes with new operator
  • Weave virtual methods/properties
  • Weave static methods/properties
  • Weave extension methods
  • Weave constructors

Advice Based Programming Model

Start with version 2, this tool support advice based programming model. Advice based programming model has these superiorities comparing to the old decorator based programming model in version 1:

  • Easy to intercept async method without thread blocking
  • Simple to control the flow and add "before", "after", "around" and "exception" advises
  • Allow to advise methods with parameters of reference type, value type and generic type, ref parameters and out parameters are allowed, too.

Your Code

public class MyAdvice : AdviceAttribute
{
    public override object Advise(IInvocation invocation)
    {
        // do something before target method is Called
        // ...
        Trace.WriteLine("Entering " + invocation.Method.Name);

        try
        {
            return invocation.Proceed();	// call the next advice in the "chain" of advice pipeline, or call target method
        }
        catch (Exception e)
        {
            // do something when target method throws exception
            // ...
            Trace.WriteLine("MyAdvice catches an exception: " + e.Message);
            throw;
        }
        finally
        {
            // do something after target method is Called
            // ...
            Trace.WriteLine("Leaving " + invocation.Method.Name);
        }
    }

    public override async Task<object> AdviseAsync(IInvocation invocation)
    {
        // do something before target method is Called
        // ...
        Trace.WriteLine("Entering async " + invocation.Method.Name);

        try
        {
            return await invocation.ProceedAsync().ConfigureAwait(false);	// asynchronously call the next advice in advice pipeline, or call target method
        }
        catch (Exception e)
        {
            // do something when target method throws exception
            // ...
            Trace.WriteLine("MyAdvice catches an exception: " + e.Message);
            throw;
        }
        finally
        {
            // do something after target method is Called
            // ...
            Trace.WriteLine("Leaving async " + invocation.Method.Name);
        }
    }
}

[MyAdvice]
public class MyClass
{
	public int Add(int x, int y)
	{
		return x + y;
	}

	public Task<int> AddAsync(int x, int y)
	{
		await Task.Dely(1000).ConfigureAwait(false);
		return x + y;
	}
}

The first time when you compile MyClass class, FodyWeavers.xml and FodyWeavers.xsd are generated if they do not exist yet. FodyWeavers.xml content likes this below:

<?xml version="1.0" encoding="utf-8"?>
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
  <CompileTimeWeaver />
</Weavers>

If (1) your MyClass and MyAdvice are in different assemblies and (2) your target platform is netstandard, you need
to manually add the full name of MyAdvice class into AdviceAttributes property of CompileTimeWeaver section in FodyWeavers.xml file
as below (suppose the namespace of MyAdvice is Advices here):

  <CompileTimeWeaver AdviceAttributes="Advices.MyAdvice" />

To add more advice classes into AdviceAttributes property, seperate them with '|' delimitor, for example: AdviceAttributes="Advices.MyAdvice1|Advices.MyAdvice2".

You do not have to change this file if your target is .net Framework or MyClass and MyAdvice are in same assembly.

Notes:

  • When multiple advices are applied to a method, the advices are invoked as a pipe line, the Advise() or AdviseAsync() of the first advice is called first.
  • When an advice is applied to class level, it is identical to this advice is added on each constructor and each method.
  • Class level advices appears before all constructor/method level advices
  • Each advice is assigned an Order, it is the sequence number of the appearance in the type group.
  • Each advice on a recursive method is invoked only when the method was entered at the very first time, re-entrances don't invoke the advice again, for performance reason.

Release Notes

- Support Netstandard 2.0 and Framework 4.6.1
     - Abandoned support to Decorator Based Programming Model

  • .NETFramework 4.6.1

  • .NETStandard 2.0

Version History

Version Downloads Last updated
3.1.7 120 2/6/2019
2.3.0 11,241 5/2/2017
2.2.1 236 4/30/2017
2.1.1 247 4/9/2017
2.1.0 230 4/9/2017
2.0.1 248 3/26/2017
2.0.0 235 3/24/2017
1.4.3 272 3/11/2017
1.4.2 267 3/8/2017
1.4.1 258 3/8/2017
1.3.0 265 2/27/2017
1.1.0 279 2/23/2017
1.0.0 258 2/23/2017