Alwyn
Alwyn

Reputation: 8337

Unity intercept change call handler based on method annotation

I have a method in a class as follow that I want to intercept:

[CustomTag1(Order = 0)]
[CustomTag2(Order = 1)]
public virtual DoSomething()

How can I inject the order value into ICallHandler.Order property, when using CustomAttributeMatchingRule?

I don't want the order to be hard coded to the handler itself or at registration. I want it to be a variable of the Order property of the method annotation.

Upvotes: 4

Views: 1756

Answers (1)

Isaac Abraham
Isaac Abraham

Reputation: 3512

I've achieved this using the HandlerAttribute - in general I use this anyway for attribute-style interception in Unity simply because you don't have to bother creating policies manually - instead you just apply a HandlerAttribute to your code and Unity will automatically create a policy for you.

Anyway, something like this is probably what you are after. First define a call handler as usual except parameterise it: -

public class MyCallHandler : ICallHandler
{
    public MyCallHandler(Int32 value)
    {
        Order = value;
    }

    public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
    {
        Console.WriteLine("Parameterised call handler!");
        return getNext()(input, getNext);
    }

    public int Order { get; set; }
}

Now instead of using the CustomTagAttribute, use a HandlerAttribute:-

public class MyHandler : HandlerAttribute
{
    private readonly Int32 value;
    public MyHandler(Int32 value)
    {
        this.value = value;
    }

    public override ICallHandler CreateHandler(IUnityContainer container)
    {
        return new MyCallHandler(value);
    }
}

The MyHandler is applied on your class. The CreateHandler method gets called, at which point it creates an instance MyCallHandler: -

public class MyClass
{
    [MyHandler(2)] // Order of 2
    public virtual void Foo()
    {
        Console.WriteLine("Inside method!");
    }
}

Note that I've deliberately separated the two classes but in reality you can just have one class implement both the ICallHandler interface and the HandlerAttribute abstract method (just return "this").

You could probably achieve something similar without the HandlerAttribute, using your own custom attribute, but it saves you time as you don't need to mess around with creating your own policies.

One thing to note - if you take a parameterised approach, you cannot have your call handlers as singletons, since a different instance will be created every time depending on what order you want it to be in.

Upvotes: 7

Related Questions