0

Unity v2.1 で Inteception パイプラインに使用している 3 つの属性があります。すべてが適切に起動しており、順序が間違っているだけです。

3 つの属性すべてで、対応する Handler に属性から Order を渡していることを確認しました。

したがって、以下の TestClass.TestProperty でセッターを呼び出すと、呼び出しハンドラーがValidation、Transaction、Notify の順序で呼び出されることを期待しています。私が見ているのはNotify, Transaction, Validationです。

グーグルを使っても答えが見つからないという 2 つの質問があります。

  1. TestClass.TestProperty を設定する私の例では、最初にプロパティ属性を呼び出し、次にクラス属性を呼び出すと仮定していますか? または、Unity は私の命令を尊重する必要がありますか?
  2. 2 つのプロパティ ハンドラーが最初に呼び出された場合、 Notify, Transactionは表示されません。Transaction と Notify Order のデフォルトをそれぞれ 1 と 2 にオーバーライドすると、期待どおりにTransaction, Notifyが得られます。私の注文が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;
        }
    }
    
4

1 に答える 1

0

私にとっては正しい順序で発射されているようです。ここに私のサンプルコードがあります:

[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;
    }
}

VirtualMethodInterceptor を使用できるように、TestProperty プロパティを仮想にしました。登録とテストコードは次のとおりです。

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;
    }
}

このコードを実行すると、次のように表示されます。

検証!
取引!
通知!

ValidationAttribute コンストラクターの順序引数を 9 ( [Validation(9)]) に変更すると、検証が期待どおり最後に行われることがわかります。

于 2013-10-17T01:19:34.223 に答える