Skip to content
Creating proxies at compile time.
Branch: master
Clone or download
BrunoJuchli Merge pull request #14 from BrunoJuchli/GenericMethods
Add Support for Generic Methods & Make StaticProxy.Interceptor a netstandard package
Latest commit 3071c99 Jul 29, 2017
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
Icons moved everything to new repository. Apr 5, 2014
IntegrationTests added support for proxying generic classes Jul 28, 2017
NuGet StaticProxy.Fody: updated release notes Jul 28, 2017
StaticProxy.Fody.Tests StaticProxy: Added missing unit tests Jul 28, 2017
StaticProxy.Fody added support for proxying generic classes Jul 28, 2017
StaticProxy.Interceptor.Tests Generic-method support StaticProxy.Interceptor. Breaking interface ch… Jul 27, 2017
StaticProxy.Interceptor changing back to NetStandardLibrary 1.6.1 Jul 28, 2017
TestAssemblies StaticProxy: Added missing unit tests Jul 28, 2017
Tools Solving weaving in IntegrationTests of StaticProxy Jul 24, 2017
.gitattributes moved everything to new repository. Apr 5, 2014
.gitignore updated to new MOQ version Mar 7, 2017
README.md Update README.md Jul 28, 2017
StaticProxy.Fody.Build.bat gitlink: ignoring Nuget project Apr 10, 2016
StaticProxy.Fody.sln adding tests for generic methods Jul 22, 2017
StaticProxy.Fody.sln.DotSettings moved everything to new repository. Apr 5, 2014
StaticProxy.Fody.yml Generic-method support StaticProxy.Interceptor. Breaking interface ch… Jul 27, 2017
StaticProxy.Interceptor.Build.bat improved build script Apr 14, 2016
StaticProxy.Interceptor.sln Moved to VS2017 style csproj config files and also changed StaticProx… Jul 18, 2017
StaticProxy.Interceptor.sln.DotSettings added seperate test project for StaticProxy.Interceptor assembly. Apr 5, 2014
StaticProxy.Interceptor.yml Generic-method support StaticProxy.Interceptor. Breaking interface ch… Jul 27, 2017
chocolatey-packages.config improved build scripts Apr 14, 2016

README.md

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

.net standard 1.0+ compatible.

Icon This is an add-in for Fody

StaticProxy weaves proxies at compile time. This is similar to tools like Castle Dynamic Proxy and LinFu Proxy, but it works during compilation (also see: Introduction to Fody). But why? Because some platforms, notably WinRT, Windows Phone and iOS do not support dynamic code emitting. So "dynamic proxy" cannot be used on these platforms. StaticProxy to the rescue!

(StaticProxy works with all .net standard 1.0+ compatible platforms, including .NET (full) Framework, .NET Core, Xamarin.IOS, Xamarin.Android, Universal Windows Platform and more)

Nuget

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

To Install the static proxy weaver and the interceptor infrastructure from the Nuget Package Manager Console

PM> Install-Package StaticProxy.Fody
PM> Install-Package StaticProxy.Interceptor

Usage

  • Add the StaticProxy.Fody and StaticProxy.Interceptor nuget packages 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(s) 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

You can’t perform that action at this time.