3

I'm using Autofac.Extras.DynamicProxy2 to perform some method interception on a service implementation.

The service has quite a few methods and I only want to target a few.

Is there a better practice besides than checking for invocation target name against an approved string dictionary of methods I want to intercept?

   public void Intercept(IInvocation invocation)
    {
        invocation.Proceed();
        if (ContinueIntercept(invocation))
        {
            // Do intercept work
        }
    }

    private bool ContinueIntercept(IInvocation invocation)
    {            
        // Logic to compare invocation.MethodInvocationTarget.Name 
    }

It really doesn't add all that much over head, but it still feels like a poor way to do it. Especially since adding this to a specific service implementation means it will intercept all of the method calls of the base class common implementation. It wouldn't be as bad if it only intercepted the derived class.

I see that Castle.DynamicProxy2 has ways to specify invocation target, but I don't see how to wire that up with autofac.

Cyril Durand
  • 15,834
  • 5
  • 54
  • 62
twifosp
  • 277
  • 2
  • 7
  • 16
  • I haven't tried it, but the [docs](http://autofac.readthedocs.org/en/latest/advanced/interceptors.html) say "Class interception requires the methods being intercepted to be virtual since it uses subclassing as the proxy technique.", so you could try removing the virtual modifier. – thinkOfaNumber Apr 22 '15 at 02:40

1 Answers1

4

You can use a IProxyGenerationHook to specify on which method the ProxyBuilder should generate a proxy.

public class FooProxyGenerationHook : IProxyGenerationHook
{
    public void MethodsInspected()
    { }

    public void NonProxyableMemberNotification(Type type, MemberInfo memberInfo)
    { }

    public Boolean ShouldInterceptMethod(Type type, MethodInfo methodInfo)
    {
        if (type == typeof(Foo) && methodInfo.Name == "Do")
        {
            return true;
        }
        return false;
    }
}

Then, you can register it this way :

    ProxyGenerator generator = new ProxyGenerator();
    FooProxyGenerationHook hook = new FooProxyGenerationHook();
    IFoo foo = generator.CreateClassProxyWithTarget<Foo>(new Foo(), new ProxyGenerationOptions(hook), new FooInterceptor());

In order to avoid calling the IProxyGenerationHook for each proxy, you should have only one instance of hook.

With DynamicProxy2, you can use this code :

    FooProxyGenerationHook hook = new FooProxyGenerationHook();

    ContainerBuilder builder = new ContainerBuilder();
    builder.RegisterType<FooInterceptor>().AsSelf();
    builder.RegisterType<Foo>().As<IFoo>()
            .EnableClassInterceptors(new ProxyGenerationOptions(hook))
            .InterceptedBy(typeof(FooInterceptor));
Cyril Durand
  • 15,834
  • 5
  • 54
  • 62
  • +1 from me. It's worthwhile pointing out that "[for performance reasons] always override Equals/GetHashCode methods on all your classes implementing IProxyGenerationHook" https://github.com/castleproject/Core/blob/master/docs/dynamicproxy-generation-hook-override-equals-gethashcode.md – Alex KeySmith Mar 23 '16 at 15:41
  • However with this approach, you still have to maintain a list of methods to be intercepted in this ShouldInterceptMethod() method. Is there a way to use attribute in *method* level *with parameters* like [Logging(OutputLevel="Verbose")]? – Calvin Aug 03 '16 at 22:16
  • @Calvin : in the shouldintercept method you can access attributes of the method by using the GetCustomAttributes method – Cyril Durand Aug 04 '16 at 05:41