Difference in the order when executing Unity HandlerAttributes assigned to class and property

StackOverflow https://stackoverflow.com/questions/19414980

質問

I have 3 attributes I am using for my Inteception pipeline in Unity v2.1. Everything is firing off properly they are just in the wrong order.

In all 3 Attributes I have made sure I am passing the corresponding Handler the Order from the attribute.

So if I call the setter on the TestClass.TestProperty below I am expecting that the call handlers should be called in this order: Validation, Transaction, Notify. What I am seeing is Notify, Transaction, Validation.

I have 2 questions here that I can't find answers to using googling around.

  1. In my example of setting the TestClass.TestProperty is it suppose to call the property attributes first then the class ones? Or should Unity respect my Order?
  2. If the 2 property handlers are called first should I not see Notify, Transaction. If I override the Transaction and Notify Order defaults to 1 and 2 respectively I get Transaction, Notify as expected. Should it matter that my order start at 1.

    [AttributeUsage(AttributeTargets.Class)
    public class ValidationAttribute : HandlerAttribute
    {
      public ValidationAttribute(int order = 1)
      {
        Order = order
      }
      public override ICallHandler CreateHandler(IUnityContainer container)
      {
        var ValidationHandler = container.Resolve<ValidationHandler>();
        ValidationHandler.Order = Order;
      }
    }
    
    public class TransactionAttribute : HandlerAttribute
    {
      public TransactionAttribute (int order = 2)
      {
        Order = order
      }
    
      // Same CreateHandler as above resolving correct handler
    }
    
    public class NotifyAttribute : HandlerAttribute
    {
      public NotifyAttribute (int order = 3)
      {
        Order = order
      }
    
      // Same CreateHandler as above resolving correct handler
    }
    
    // Didn't include handler code to keep short(ish). All handlers have logging to show they are executing
    ...
    
    [Validation]
    public class TestClass
    { 
        public int TestProperty
        {
          get;
          [Transaction]
          [Notify]
          set;
        }
    }
    
役に立ちましたか?

解決

It seems to be firing off in the correct order for me. Here is my sample code:

[AttributeUsage(AttributeTargets.Class)]
public class ValidationAttribute : HandlerAttribute
{
    public ValidationAttribute(int order = 1)
    {
        Order = order;
    }

    public override ICallHandler CreateHandler(IUnityContainer container)
    {
        var handler = container.Resolve<ValidationHandler>();
        handler.Order = Order;
        return handler;
    }
}

public class TransactionAttribute : HandlerAttribute
{
    public TransactionAttribute(int order = 2)
    {
        Order = order;
    }

    public override ICallHandler CreateHandler(IUnityContainer container)
    {
        var handler = container.Resolve<TransactionHandler>();
        handler.Order = Order;
        return handler;
    }
}

public class NotifyAttribute : HandlerAttribute
{
    public NotifyAttribute(int order = 3)
    {
        Order = order;
    }

    public override ICallHandler CreateHandler(IUnityContainer container)
    {
        var handler = container.Resolve<NotifyHandler>();
        handler.Order = Order;
        return handler;
    }
}

public class ValidationHandler : ICallHandler
{

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

    public int Order
    {
        get;
        set;
    }
}

public class TransactionHandler : ICallHandler
{
    public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
    {
        Console.WriteLine("Transaction!");
        return getNext().Invoke(input, getNext);
    }

    public int Order
    {
        get;
        set;
    }
}

public class NotifyHandler : ICallHandler
{
    public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
    {
        Console.WriteLine("Notify!");
        return getNext().Invoke(input, getNext);
    }

    public int Order
    {
        get;
        set;
    }
}

[Validation]
public class TestClass
{
    public virtual int TestProperty
    {
        get;
        [Transaction]
        [Notify]
        set;
    }
}

I made the TestProperty property virtual so I could use the VirtualMethodInterceptor. Here is the registration and test code:

class Program
{
    static void Main(string[] args)
    {
        IUnityContainer container = new UnityContainer();
        container.AddNewExtension<Interception>();

        container.RegisterType<ValidationHandler>(new ContainerControlledLifetimeManager());
        container.RegisterType<TransactionHandler>(new ContainerControlledLifetimeManager());
        container.RegisterType<NotifyHandler>(new ContainerControlledLifetimeManager());

        container.RegisterType<TestClass>(
            new InterceptionBehavior<PolicyInjectionBehavior>(),
            new Interceptor<VirtualMethodInterceptor>()); 

        var testClass = container.Resolve<TestClass>();

        testClass.TestProperty = 5;
    }
}

When I run this code I see:

Validation!
Transaction!
Notify!

If I change the order argument to the ValidationAttribute constructor to 9 ([Validation(9)]) then I see Validation happening last as expected.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top