Using multiple proxy generation hooks for creating a proxy

462 views Asked by At

Let's say I have a type like this:

public class Foo
{
    public virtual void InterceptedByA() { }

    public virtual void InterceptedByB() { }
}

I have two selectors named InterceptorA and InterceptorB. I want to use multiple IProxyGenerationHook implementations to ensure they only intercept their own methods. ProxyGenerator class accepts an array of interceptors but I can only use single IProxyGenerationHook instance in ProxyGenerationOptions constructor:

var options = new ProxyGenerationOptions(new ProxyGenerationHookForA());

Is there a way to use multiple IProxyGenerationHook implementations for creating a proxy?

1

There are 1 answers

0
samy On

The IProxyGenerationHook is used at proxy-ing time only once for the object being proxy-ed. If you want fine-grained control about which interceptors are used for a method you should use the IInterceptorSelector

Here is a (very stupid) example that could help you see how you could use the IInterceptorSelector to match the methods called. Of course you wouldn't rely on the method names in order to match the selectors but this is left as an exercice

internal class Program
{
    private static void Main(string[] args)
    {
        var pg = new ProxyGenerator();

        var options = new ProxyGenerationOptions();
        options.Selector = new Selector();
        var test = pg.CreateClassProxy<Foo>(options, new InterceptorA(), new InterceptorB());

        test.InterceptedByA();
        test.InterceptedByB();
    }
}

public class Foo
{
    public virtual void InterceptedByA() { Console.WriteLine("A"); }
    public virtual void InterceptedByB() { Console.WriteLine("B"); }
}


public class Selector : IInterceptorSelector
{
    public IInterceptor[] SelectInterceptors(Type type, System.Reflection.MethodInfo method, IInterceptor[] interceptors)
    {
        return interceptors.Where(s => s.GetType().Name.Replace("or", "edBy") == method.Name).ToArray();
    }
}

public class InterceptorA : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        Console.WriteLine("InterceptorA");
        invocation.Proceed();
    }
}
public class InterceptorB : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        Console.WriteLine("InterceptorB");
        invocation.Proceed();
    }
}