Search code examples
c#aopautofaccastle-dynamicproxy

How to use Autofac with DynamicProxy to determine the namespace of the target proxy class


I'm using the IInterceptor to Intercept method invocations in certain classes. The interceptor is set up like so:public class InstrumentationInterceptor: IInterceptor { public InstrumentationInterceptor() { Measure.Configure(new StatsdConfig()); }

    public void Intercept(IInvocation invocation)
    {
        var instrumentationId = new StringBuilder();
        instrumentationId.Append(typeof(Program).Namespace.Replace(".", string.Empty).ToLower());
        instrumentationId.Append(".");
        instrumentationId.Append("response");
        instrumentationId.Append(".");
        // The following will split the camel case simple name of the proxied class,
        //  where 'Consumer' suffix has been removed, and also convert to lower case
        instrumentationId.Append(Regex.Replace(invocation.TargetType.Name.Replace("Consumer", string.Empty), "(\\B[A-Z])", "_$1").ToLowerInvariant());
        instrumentationId.Append(".");
        instrumentationId.Append("duration");
        using (
            Measure.StartTimer(instrumentationId.ToString()))
        {
            invocation.Proceed();
            Measure.Counter(instrumentationId.ToString(), 1);
        }
    }
}

This is then wired up like so in an Autofac module:

var builder = new ContainerBuilder();
builder.RegisterType<DataConsumer>().
            As<IConsumer<DataRequest>>().
            EnableInterfaceInterceptors().
            InterceptedBy(typeof (InstrumentationInterceptor));
builder.Build();

I'm using this to measure time taken and count instances this method is called. I'd like to be able to push this to an external library I have, but I'll loose the ability to get the Namespace of the calling Program. Is there any way to use the IInvocation to get to the target namespace?

Any thoughts on this would be useful.

Thanks.


Solution

  • You can use the GetConcreteMethodInvocationTarge method in invocation to get the MethodInfo instance that you are actually intercepting.

    GetConcreteMethodInvocationTarget :

    • Summary: Returns the concrete instantiation of IInvocation.MethodInvocationTarget, with any generic parameters bound to real types. For interface proxies, this will point to the System.Reflection.MethodInfo on the target class.
    • Returns: The concrete instantiation of IInvocation.MethodInvocationTarget, or IInvocation.MethodInvocationTarget if not a generic method.

    With the MethodInfo you can get the type and then the namespace.

    String namespace = invocation.GetConcreteMethodInvocationTarget().DeclaringType.Namespace;
    

    Another solution would be to use the InvocationTarget property and then calling the .GetType() method to retrieve the intercepted type but in some complexe case it may not work.

    String namespace = invocation.InvocationTarget.GetType().Namespace;