Search code examples
c#unity-containeraopunity-interception

.NET Unity Interception using Custom Attributes


I would like to get the behaviour described in the answer here but using configuration through code. The code sample shows custom attribute being created without anything unity related and adding the behaviour through configuration.

Custom attribute is in the separate assembly referenced in the same solution.

Problem is that it throw an exception during configuration:

InvalidOperationException: The type Microsoft.Practices.Unity.InterceptionExtension.CustomAttributeMatchingRule does not have a constructor that takes the parameters (LogAttribute, Boolean).

container
    .AddNewExtension<Interception>()
    .Configure<Interception>()
        .AddPolicy("MyLoggingPolicy")
        .AddMatchingRule<CustomAttributeMatchingRule>(
        new InjectionConstructor(typeof(Abstractions.Attributes.LogAttribute), true))
        .AddCallHandler<LoggingHandler>(new ContainerControlledLifetimeManager())
            .Interception
            .Container
        .RegisterType<IFirstInterface>(new InjectionFactory((context) => FirstClassFactoryMethod()))
        .RegisterType<ISecondInterface>(new InjectionFactory((context) => SecondClassFactoryMethod()));

[AttributeUsage(AttributeTargets.Method)]
public class LogAttribute : Attribute { }

public class LoggingHandler : ICallHandler
{
    public int Order { get; set; }

    public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
    {
        Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss")} Started: {input.MethodBase.Name}");
        var result = getNext()(input, getNext);
        Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss")} Completed: {input.MethodBase.Name}");
        return result;
    }
}

Updating the line that throws to:

.AddMatchingRule(
    new CustomAttributeMatchingRule(typeof(Abstractions.Attributes.LogAttribute), true))

prevents the exception from being thrown, but the LoggingHandler does not recieve any calls from the methods that have the [Log] attribute.

NOTE: Methods marked with [Log] are public methods, in a different assembly, in classes that are instantiated using .Resolve().


Solution

  • For anyone that encounters the same problem - I had to define the interception behavior on the registered types:

    .RegisterType<IFirstInterface>(
        new InjectionFactory((context) => FirstClassFactoryMethod())
        new Interceptor<TransparentProxyInterceptor>()
        new InterceptionBehavior<PolicyInjectionBehavior>())
    .RegisterType<ISecondInterface>(
        new InjectionFactory((context) => SecondClassFactoryMethod())
        new Interceptor<TransparentProxyInterceptor>()
        new InterceptionBehavior<PolicyInjectionBehavior>()));