2014-12-20 3 views
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 
     } 
} 

객체가 단결 컨테이너에 등록되어

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

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

불행하게도 항상 내 인터셉터는 ExecuteMyCommand() 방법에 대해 호출됩니다. 그러한 차단을 할 수 있습니까? 제가 단합 컨테이너를 통해 노력하고 있습니까? 나는 천천히 AOP 라이브러리 인 Spring.NET을 통해 그것을 성취하려고 노력 중이다.

+0

질문을 업데이트하고 객체 그래프의 모양을 보여줄 수 있습니까 (예 :이 객체 그래프를 수동으로 작성하면 코드가 어떻게 생겼을까요?). 그리고 추가하려는 크로스 커팅 문제는 무엇입니까? – Steven

+0

오브젝트 그래프는 다른 오브젝트에 의존하는 여러 오브젝트에 의존하기 때문에 다소 분기점이 있습니다. CustomSerialDevice 클래스는 다른 객체에 대해 여러 종속성이 있지만 유니티 컨테이너 범위 내의 단일 객체입니다. 따라서 새 CustomSerialDevice {Dependency1 = new Dependency1 {Dependency2 = new Dependency2()} ....와 같은 것이 될 수 있습니다. . 이것이 첫 번째 질문에서 의미했던 것입니까?CustomSerialDevice의 메소드 (또한 inhereted 메소드) 각각에 대해 일반적인 예외 처리를 수행해야했습니다. –

+0

정확히는 유형의 실제 이름을 표시하는 것을 보았습니다. 문제는 디자이너가 설계상의 결함으로 인해 교차 절단 문제를 적용하기 위해 (예를 들어 데코레이터 사용과 비교할 때) 가로 채기를 다시 시도하는 것을 종종 봅니다. 우리가 디자인을 볼 수 있고 그러한 크로스 커팅 문제를 어떻게 적용하려고하면 디자인에 대한 피드백을 얻을 수 있습니다. – Steven

답변

2

먼저 가능한 한 InterfaceInterceptor를 사용하는 것이 좋습니다. 최고의 유연성과 성능을 제공합니다. InterfaceInterceptor를 사용할 수 없을 때 VirtualMethodInterceptor를 사용하십시오. 마지막 수단으로 TransparentProxyInterceptor를 사용하십시오. here을 참조하십시오.

인터페이스의 경우 처리기 속성은 해당 인터페이스에 정의 된 메서드에만 적용됩니다 (상속되지 않음). 따라서 [MyHandler] 속성을 사용하여 4 개의 인터페이스를 모두 꾸미면 나만의 것을 얻을 수 있습니다.

구체적인 클래스의 경우 처리기 특성은 상속 된 모든 유형에 적용됩니다. 따라서 최상위 AbstractSerialDevice를 [MyHandler] 속성으로 꾸미면 여러분이 원하는 것을 얻을 수 있습니다. 인터페이스 또는 구체적인 클래스 수준에서 개별 메서드를 꾸밀 수도 있습니다.

또한 제 생각에 구체적인 방법을 꾸미는 것이 한 가지 유형을 꾸미는 것보다 조금 더 쉽게 발견 할 수 있습니다. 그것은 좀 더 장황하다.


옵션 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*/ } 
} 

이러한 옵션은 모두 사용할 수 있습니까?

+1

나는이 결과에 조금 놀랐다. 예기치 못한 것을 지적 해 주셔서 감사한다. 이러한 종류의 단점에 대한 지식은 가치가 있습니다. – TylerOhlsen

+1

좋은 답변 주셔서 감사합니다. 세 번째 옵션은 완벽하게 작동합니다. –