4

継承の深さが 3 のオブジェクト構造を持っています。オブジェクトは、単一の特定のインターフェイスを実装しています。インターフェイスの継承の深さは 4 です。私の最終的なオブジェクトは、ユニティ IoC を介して構築されています。このオブジェクトのすべてのパブリック メソッドをインターセプトする必要があります (どのインターフェイスで定義されているかに関係なく) が、使用するインターセプターの種類 (InterfaceInterceptor/TransparentProxyInterceptor/VirtualMethodInterceptor ) に関係なく、継承ツリーの最終クラスで定義されたメソッドのみを常にインターセプトします。以下のオブジェクト構造の図を参照してください。

public interface IDevice {
    void Connect();
}

public interface ISerialDevice {
   void WriteCommand();
}

public interface IProtocolSerialDevice {
   void ExecuteProtocolCommand();
}

[MyHandler]
public interface ICustomSerialDevice {
   void ExecuteMyCommand();
}

public abstract class AbstractSerialDevice {
   public virtual void WriteCommand() {
        //omitted
   }
}

public abstract class AbstractProtocolSerialDevice : AbstractSerialDevice {
    public virtual void ExecuteProtocolCommand() {
         //omitted
    }
}


public class CustomSerialDevice : AbstractProtocolSerialDevice, ICustomSerialDevice {
      public virtual void ExecuteMyCommand() {
            //omitted
      }
}

public class MyHandlerAttribute : HandlerAttribute {
      public override ICallHandler CreateHandler(IUnityContainer container) {
         //omitted
      }
}

オブジェクトは次のように Unity コンテナーに登録されます。

container.RegisterType<ICustomSerialDevice, CustomSerialDevice>(
   new ContainerControlledLifetimeManager(),  new InjectionMethod(postConstructMethodName));

container.Configure<Interception>()
         .SetInterceptorFor<ICustomSerialDevice>(new TransparentProxyInterceptor());

残念ながら、私のインターセプターは常にExecuteMyCommand()メソッドに対してのみ呼び出されます。Unityコンテナを介して私が目指しているそのような傍受を行うことは可能ですか? Spring.NET AOP ライブラリを介してそれを達成しようとゆっくり考えています。

4

1 に答える 1

2

まず、可能な限り InterfaceInterceptor を使用することをお勧めします。最高の柔軟性とパフォーマンスを提供します。InterfaceInterceptor を使用できない場合は、VirtualMethodInterceptor の使用にフォールバックします。最後の手段として、TransparentProxyInterceptor を使用してください。ここを参照してください。

インターフェイスの場合、handler 属性はそのインターフェイスで定義されたメソッドにのみ適用されます (継承されません)。したがって、[MyHandler] 属性を使用して 4 つのインターフェイスすべてを装飾することで、目的を達成できます。

具象クラスの場合、handler 属性は継承されたすべての型に適用されます。したがって、[MyHandler] 属性を使用して上部の AbstractSerialDevice を装飾することで、目的を達成できます。インターフェイスまたは具体的なクラス レベルで個々のメソッドをデコレートすることもできます。

また、私の意見では、具体的なメソッドを装飾することは、型を装飾することよりも少し発見しやすいです。もう少し冗長ですが。


オプション1

// No MyHandler on any of the concrete classes

[MyHandler]
public interface IDevice
{ /* omitted */ }

[MyHandler]
public interface ISerialDevice : IDevice
{ /* omitted */ }

[MyHandler]
public interface IProtocolSerialDevice : ISerialDevice
{ /* omitted */ }

[MyHandler]
public interface ICustomSerialDevice : IProtocolSerialDevice
{ /* omitted */ }

オプション 2

// No MyHandler on any of the interfaces nor derived classes

[MyHandler]
public abstract class AbstractSerialDevice : ISerialDevice
{ /* omitted */ }

オプション 3

// No MyHandler on any of the interfaces nor abstract classes

public class CustomSerialDevice : AbstractProtocolSerialDevice, ICustomSerialDevice
{
    [MyHandler]
    public override void Connect()
    { base.Connect(); }

    [MyHandler]
    public override void WriteCommand()
    { base.WriteCommand(); }

    [MyHandler]
    public override void ExecuteProtocolCommand()
    { base.ExecuteProtocolCommand(); }

    [MyHandler]
    public void ExecuteMyCommand()
    { /*omitted*/ }
}

これらのオプションのいずれかがあなたのために働きますか?

于 2014-12-21T04:18:04.920 に答える