Skip to content

OmerRaviv/StaticProxy.Fody

 
 

Repository files navigation

StaticProxy.Fody: Build status StaticProxy.Interceptor: Build status

Icon This is an add-in for Fody

Very cool utilities have been created by the help of proxying by dynamic code emitting: Moq, FakeItEasy, Castle Dynamic Proxy, LinFu Proxy,.. and many more.

Sadly enough, some platforms do not support dynamic code emitting. These include Windows Store Applications (WinRT), Windows Phone 7 and Xamarin.iOS.

Here comes StaticProxy.Fody to the rescue! Instead of dynamically creating proxies, it is weaving them at compile time by means of IL rewritting (see: Introduction to Fody).

It is meant to be used in conjunction with dependency injection containers since it is adding arguments to the constructor - and thus breaks new Foo(...) calls of all proxied classes.

Nuget

Nuget package http://nuget.org/packages/StaticProxy.Fody

To Install the static proxy weaver from the Nuget Package Manager Console

PM> Install-Package StaticProxy.Fody

Usage

  • Add the StaticProxy.Fody nuget package to any project where you wish to add static proxy weaving.
  • Put an [StaticProxy] attribute on any class or interface you wish to be proxied.
  • Write interceptors (class SomeProxy : IDynamicInterceptor)

Then, use one of the existing StaticProxy IoC container integrations:

or roll your own:

  • Configure your Inversion of Control (IoC) container to be able to resolve IDynamicInterceptorManager. The implementation is provided by the StaticProxy.Interceptor nuget package.
  • Configure your IoC container to be able to resolve IDynamicInterceptorCollection. It needs to contain the interceptor for the proxied type.

Class Proxy

Is created by putting the [StaticProxy] attribute on a class. This is similar to castle dynamic proxy "class proxy" and "interface proxy with target". The class will be decorated, so that all method calls can be intercepted.

Your Code

[StaticProxy]
public class Foo
{
    private readonly IBar bar;

    public Foo(IBar bar)
    {
        this.bar = bar;
    }

    public int Multiply(int multiplicand , int multiplier)
    {
        return multiplicand * multiplier;
    }
    
    public void NoReturnValue(string value)
    {
        Console.WriteLine(value);
    }
}

What gets compiled

public class Foo
{
    private readonly IBar bar;
    private readonly IDynamicInterceptorManager dynamicInterceptorManager;

    public Foo(IBar bar, IDynamicInterceptorManager IDynamicInterceptorManager)
    {
        this.bar = bar;
        this.dynamicInterceptorManager = dynamicInterceptorManager;
        this.dynamicInterceptorManager.Initialize(this, false);
    }

    public int Multiply(int multiplicand , int multiplier)
    {
        object[] arguments = new object[] { multiplicand, multiplier };
        MethodInfo decoratedMethod = methodOf(Multiply);
        MethodInfo implementationMethod = methodOf(Multiply<SP>);
    
        return this.dynamicInterceptorManager.Intercept(decoratedMethod, implementationMethod, arguments);
    }

    public int Multiply<SP>(int multiplicand , int multiplier)
    {
        return multiplicand * multiplier;
    }
    
    public void NoReturnValue(string value)
    {
        object[] arguments = new object[] { value };
        MethodInfo decoratedMethod = methodOf(NoReturnValue);
        MethodInfo implementationMethod = methodOf(NoReturnValue<SP>);
    
        this.dynamicInterceptorManager.Intercept(decoratedMethod, implementationMethod, arguments);
    }
    
    public void NoReturnValue<SP>(string value)
    {
        Console.WriteLine(value);
    }
}
Explanation
  • IDynamicInterceptorManager argument is added to the constructor
  • the constructor passes a reference to the newly created object to the IDynamicInterceptorManager by way of .Initialize(this, false);
  • all public methods are renamed from Orig(..) to (Orig<SP>(...). For each a decorating method with the original signature is created.
  • The decorating method is passing every call to the IDynamicInterceptorManager by .Intercept(..).
  • The IDynamicInterceptorManager is calling the IDynamicInterceptors in sequence and lastly the implementation.

Interface Proxy

Is created by putting the [StaticProxy] attribute on an interface. This is similar to castle dynamic proxy "interface proxy without target". An implementation of the interface is created. This implementation will call the interceptor(s). The interceptors will need to provide the actual "business" implementation of the method. Subsequently, this type of proxy does only work if there are 1+ interceptors.

Your Code

[StaticProxy]
public interface IBar
{
    int Multiply(int multiplicand , int multiplier);
    
    void NoReturnValue(string value);
}

What gets compiled

public class IBarImplementation
{
    private readonly IDynamicInterceptorManager dynamicInterceptorManager;

    public Foo(IDynamicInterceptorManager IDynamicInterceptorManager)
    {
        this.dynamicInterceptorManager = dynamicInterceptorManager;
        this.dynamicInterceptorManager.Initialize(this, true);
    }

    public int Multiply(int multiplicand , int multiplier)
    {
        object[] arguments = new object[] { multiplicand, multiplier };
        MethodInfo decoratedMethod = methodOf(Multiply);
        MethodInfo implementationMethod = null;
    
        return this.dynamicInterceptorManager.Intercept(decoratedMethod, implementationMethod, arguments);
    }
    
    public void NoReturnValue(string value)
    {
        object[] arguments = new object[] { value };
        MethodInfo decoratedMethod = methodOf(NoReturnValue);
        MethodInfo implementationMethod = null;
    
        this.dynamicInterceptorManager.Intercept(decoratedMethod, implementationMethod, arguments);
    }
}
Explanation
  • a class is added to the assembly where the interface resided. The class is named "InterfaceName" + "Implementation". The class implements the interface.
  • The class contains a constructor with IDynamicInterceptorManager argument
  • the constructor passes a reference to the newly created object to the IDynamicInterceptorManager by way of .Initialize(this, true);
  • all interface methods are implemented. They make a call to IDynamicInterceptorManager.Intercept(..).
  • The IDynamicInterceptorManager is calling the IDynamicInterceptors in sequence.

Icon

Icon courtesy of The Noun Project

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • C# 96.8%
  • PowerShell 2.6%
  • Visual Basic .NET 0.6%