Search code examples
c#unity-containeraop

C# AOP Custom attribute Unity


I'm trying to develop a custom attribute in order to decorate methods, and when I do that I want them to be "catched" by the attribute so it decides what to do with the exception.

I'm aware of specially two techniques to do this: - PostSharp - Enterprise Library Unity

I'd like to avoid the first one, I'd like to go ahead with Unity since we already use Enterprise Library.

So, in order to make this work, I've done the following:

My call handler:

public class LoggingCallHandler : ICallHandler
{
    public bool Rethrow
    {
        get; set;
    }

    public bool Log
    {
        get; set;
    }

    public int Order
    {
        get; set;
    }

    public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
    {
        var result = getNext().Invoke(input, getNext);

        if (result.Exception != null)
        {
            if (this.Rethrow)
                throw result.Exception;

            if (this.Log)
                this.LogException(result.Exception);
        }

        return result;
    }

    private void LogException(Exception ex)
    {
        //  Do stuff
    }
}

My custom attribute

public class LoggingCallHandlerAttribute : HandlerAttribute
{
    private bool rethrow;

    private bool log;

    public LoggingCallHandlerAttribute(bool rethrow, bool log = false)
    {
        this.rethrow = rethrow;
        this.log = log;
    }

    public override ICallHandler CreateHandler(IUnityContainer container)
    {
        return new LoggingCallHandler() { Rethrow = this.rethrow, Log = this.log };
    }
}

My class with the method decorated with the attribute

 public class TestManager
{
    [LoggingCallHandler(false, false)]
    public void DoStuff()
    {
        throw new Exception("TEST");
    }
}

When I run the method, no AOP happens.

I'm aware thar Unity may rely or relies at all in containers. But we don't use any of that currently, so we'd like just to decorate a method with the [LoggingCallHandler] attribute and that's it.

If container is really necessary it can be considered but it would be nice to have a single container that fits all purposes (at least for now...).

Is it possible to achieve this?

Thank you guys.


Solution

  • If you don't use Unity container to construct your objects, then the interception (via ICallHandler) will not work.

    Such interception depends on Unity to wrap your objects when you create them through the Unity DI container.

    PostSharp interception will work even if you don't use a DI container.

    If you don't use a DI container, (IMO) it might be better for you to keep things as is and don't introduce a DI container to your code base. See my article here.

    You might also want to consider doing interception using DynamicProxy. But this requires you to wrap your objects manually when you create them.