StaticProxy.Fody: StaticProxy.Interceptor:
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 package http://nuget.org/packages/StaticProxy.Fody
To Install the static proxy weaver from the Nuget Package Manager Console
PM> Install-Package StaticProxy.Fody
- 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:
- Ninject (PCL): ninject.extensions.staticproxy
- Unity Unity.StaticProxyExtension
or roll your own:
- Configure your Inversion of Control (IoC) container to be able to resolve
IDynamicInterceptorManager
. The implementation is provided by theStaticProxy.Interceptor
nuget package. - Configure your IoC container to be able to resolve
IDynamicInterceptorCollection
. It needs to contain the interceptor for the proxied type.
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.
[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);
}
}
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);
}
}
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 theIDynamicInterceptor
s in sequence and lastly the implementation.
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.
[StaticProxy]
public interface IBar
{
int Multiply(int multiplicand , int multiplier);
void NoReturnValue(string value);
}
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);
}
}
- 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 theIDynamicInterceptor
s in sequence.
Icon courtesy of The Noun Project