2014-06-20 1 views
12

좋아, 오래 걸릴 수 있습니다. 나는 두 가지 작업을 수행하려고 :포스트 샤프한 양상 주문 실행

  • 내가 모든 통화가 라우팅되는 다른 클래스의 인스턴스를 유지하여 인터페이스를 구현하는 클래스를 갖고 싶어.

  • 또한 모든 메서드 호출을 가로 채고 무언가를하고 싶습니다.

자신의 작품 모두 위대한 작품. 그것들을 결합하는 것은 하나의 실행 명령으로 만 작동하는 것으로 보이며 Murphy가 가지고있는 것처럼, 그것은 잘못된 것입니다 (적어도 저에게는).

나는 모든 전화의 차단이 또한 이전에 주입 된 것을 가로 채기 위해 첫 번째으로 주입하고 싶습니다.

namespace ConsoleApplication13 
{ 
    using System; 
    using System.Reflection; 

    using PostSharp; 
    using PostSharp.Aspects; 
    using PostSharp.Aspects.Dependencies; 
    using PostSharp.Extensibility; 

    [Serializable] 
    [ProvideAspectRole("COMPOSER")] 
    public sealed class ComposeAspectAttribute : CompositionAspect 
    { 
    [NonSerialized] 
    private readonly Type interfaceType; 

    private readonly Type implementationType; 

    public ComposeAspectAttribute(Type interfaceType, Type implementationType) 
    { 
     this.interfaceType = interfaceType; 
     this.implementationType = implementationType; 
    } 

    // Invoked at build time. We return the interface we want to implement. 
    protected override Type[] GetPublicInterfaces(Type targetType) 
    { 
     return new[] { this.interfaceType }; 
    } 

    // Invoked at run time. 
    public override object CreateImplementationObject(AdviceArgs args) 
    { 
     return Activator.CreateInstance(this.implementationType); 
    } 
    } 

    [Serializable] 
    [ProvideAspectRole("INTERCEPTOR")] 
    [MulticastAttributeUsage(MulticastTargets.Method)] 
    [AspectRoleDependency(AspectDependencyAction.Order, AspectDependencyPosition.After, "COMPOSER")] 
    public sealed class InterceptAspectAttribute : MethodInterceptionAspect 
    { 
    public override void CompileTimeInitialize(MethodBase method, AspectInfo aspectInfo) 
    { 
     base.CompileTimeInitialize(method, aspectInfo); 

     // Warning in VS output 
     Message.Write(method, SeverityType.Warning, "XXX", "Method: " + method.Name); 
    } 

    public override void OnInvoke(MethodInterceptionArgs args) 
    { 
     Console.WriteLine("Intercepted before"); 
     args.Proceed(); 
     Console.WriteLine("Intercepted after"); 
    } 
    } 

    interface ITest 
    { 
    void Call(); 
    } 

    class TestImpl : ITest 
    { 
    public void Call() 
    { 
     Console.WriteLine("CALL remote implemented"); 
    } 
    } 

    [InterceptAspect(AspectPriority = 1)] 
    [ComposeAspect(typeof(ITest), typeof(TestImpl), AspectPriority = 2)] 
    class Test 
    { 
    // this should, after compilation, have all methods of ITest, implemented through an instance of TestImpl, which get intercepted before TestImpl is called 

    public void CallLocalImplementedTest() 
    { 
     Console.WriteLine("CALL local implemented"); 
    } 
    } 


    class Program 
    { 
    static void Main() 
    { 
     var test = new Test(); 

     ITest t = Post.Cast<Test, ITest>(test); 

     Console.WriteLine("TEST #1"); 
     t.Call(); 

     Console.WriteLine("TEST #2"); 
     test.CallLocalImplementedTest(); 

     Console.ReadLine(); 
    } 
    } 
} 

는 또한 작곡가을 먼저

  • AspectPriority를 ​​실행하는 작곡가에 의존하는 인터셉터를 만드는

    • AspectRoleDependency하여 두 가지 측면의 실행 순서에 영향을 시도 먼저 실행하십시오. 테스트로

    항상

    TEST #1 
    CALL remote implemented 
    
    TEST #2 
    Intercepted before 
    CALL local implemented 
    Intercepted after 
    

    가 분명히 작동하지 않습니다를 얻을 수 있습니다. 내 처형 명령이 왜 바뀌지 않았는가? 제가 잘못 했나요? 문서의 세부 사항을 놓쳤습니까? 컴포지션 주입 방식도 가로 채기 위해 무엇을 할 수 있습니까?

  • +0

    당신은 또한 당신의 원하는 결과를 달성하기 위해'TestImpl' 클래스에'InterceptAspect'를 추가해야 . – nemesv

    +0

    @nemesv 아마도 그렇게해도 TestImpl 클래스는 내 클래스가 아닌 경우가 있습니다.나는 TestImpl을 그대로 둘 수있는 솔루션을 선호한다. – nvoigt

    +0

    다른 방법으로'ITth' 인터페이스 자체에'[InterceptAspect (AttributeInheritance = MulticastInheritance.Multicast)]를 넣을 수 있습니다. 그러나 이것이 당신이 얻을 수있는 가장 먼 것입니다. 문제는 Postsharp가 일리노이를 한 걸음 씩 흔들며, InterceptAspect를 컴파일 타임에있는 메소드에만 적용하여 새로운 ComposeAspect와 함께 구현 된 인터페이스를 볼 수 없다는 것입니다. 그래서 당신이'ComposeAspect'로 추가하는 타입은 이미'InterceptAspect'에 의해 제공된 로깅 코드를'ITest' 나'TestImpl' 클래스에 넣어야합니다. – nemesv

    답변

    2

    현재의 설정과 현재 설정으로 원하는 결과를 얻을 수 없습니다.

    문제는 어떻게 Postsharp 일이다 : 이는 IL 한 단계 흔들며 않고 단지 그래서가 첨가 된 새로운 인터페이스 구현이 표시되지 않는 원래 컴파일 시간에 존재하는 방법에 InterceptAspect 적용 ComposeAspect.

    허용 또는 역할, 우선 순위 또는 기타 구성을 제공하는 순서는 여기에 도움이되지 않습니다.

    한 가지 해결 방법은 주입 된 TestImpl 클래스에 InterceptAspect를 추가하는 것입니다 : 로깅 논리가로 구성 될 때 그래서이 방법은 로깅을 포함 직접 TestImpl 추가됩니다이 경우

    [InterceptAspect] 
    class TestImpl : ITest 
        { 
        public void Call() 
        { 
         Console.WriteLine("CALL remote implemented"); 
        } 
        } 
    

    당신의 Test 클래스입니다.

    아니면 모든 구현을 표시하지 않는 경우는과의 인터페이스 자체에 측면을 넣을 수 있습니다 :

    [InterceptAspect(AttributeInheritance = MulticastInheritance.Multicast)] 
    interface ITest 
    { 
        void Call(); 
    }