2016-09-25 4 views
1

저는 두 가지 포스트 샤프 측면이 서로 작동하는 시나리오를 디자인하고 있습니다. 하나의 측면 (FirstAspect 코드 아래에 있음) 인터페이스를 소개 할 의미가 있고 다른 측면 (코드 아래에 SecondAspect) 첫 번째 측면에서 도입 된 인터페이스로 작동하도록되어 있습니다.빌드 시간 동안 PostSharp에 의해 소개 된 인터페이스 또는 멤버 인터페이스에 액세스 할 수 있습니까?

그러나 첫 번째 측면에서 도입 된 인터페이스는 두 번째 측면에서 사용 가능한 것으로 보이지 않습니다. FirstAspect에 의해 도입 된 인터페이스는 한 번에 SecondAspect에 사용할 수 없습니다로,

public class Tests 
{ 
    [Fact] 
    public void Verify() 
    { 
     // Not really all that significant as the current code does not compile correctly: 
     var sut = new MyClass(); 
     Assert.True(sut is IInterface); 
    } 

    public interface IInterface 
    { 
     void HelloWorld(); 
    } 

    [IntroduceInterface(typeof(IInterface))] 
    public class FirstAspect : InstanceLevelAspect, IInterface, IAspectProvider 
    { 
     public void HelloWorld() {} 

     public IEnumerable<AspectInstance> ProvideAspects(object targetElement) 
     { 
      // Implementing IAspectProvider appears to ensure this aspect is processed first. 
      // This may be a bug. 
      // Please see: http://support.sharpcrafters.com/discussions/problems/3365-runtimeinitialize-does-not-follow-ordering-rules#comment_40824072 
      // for more information. 
      yield break; 
     } 
    } 

    [AspectTypeDependency(AspectDependencyAction.Order, AspectDependencyPosition.After, typeof(FirstAspect))] 
    public class SecondAspect : InstanceLevelAspect, IAspectProvider 
    { 
     public IEnumerable<AspectInstance> ProvideAspects(object targetElement) 
     { 
      var type = (Type)targetElement; 
      if (!typeof(IInterface).GetTypeInfo().IsAssignableFrom(type)) 
      { 
       // This is currently being thrown, as MyClass does not implement 
       // IInterface when the AppDomain is first loaded and initialized: 
       throw new InvalidOperationException($"Does not implement {typeof(IInterface)}"); 
      } 

      // How to access the weaved elements from FirstAspect? ... 

      yield break; 
     } 
    } 

    [FirstAspect, SecondAspect] 
    class MyClass {} 
} 
내가 구축

SecondAspect.ProvideAspectsInvalidOperationException가 발생합니다 : 여기

내가 현재 함께 일하고 코드입니다 전화가 걸린다. 즉, 인터페이스가 MyClass 유형으로 바뀌 었음에도 불구하고 유형은 현재 AppDomain 내에있는 형식이므로로드 된 인터페이스는 구현 된 것으로 표시되지 않습니다.

내가 찾고있는 것은 빌드 중에 대상 요소에 알려진 모든 인터페이스와 멤버를 액세스하고 찾을 수있는 기능입니다.

ReflectionSearch으로 보았는데, 내가 찾고있는 것에 가깝지만이 API를 호출 할 때 weaved 요소를 고려하지 않은 것 같습니다. 예를 들어 ReflectionSearch.GetMembersOfType 전화를 걸면 IInterface.HelloWorldMyClass (위의 예에서는 FirstAspect으로 표시됨)에 표시되지 않습니다.

빌드 타임 중에 PostSharp에서 소개/weaved 요소에 액세스하려면 사용해야하는 또 다른 API가 있습니까? 이것은 가능한가?

+0

포스트 샤프 측면에는 원래 유형과 메서드 만 표시되므로 빌드시에 weaved 인터페이스를 보는 방법은 없습니다. SecondAspect에서 소개 된 인터페이스로 무엇을하고 싶습니까? –

+0

답장을 보내 주셔서 감사합니다. @ JakubLinhart. 특정 인터페이스가 내 클래스에 적용되었는지 확인한 다음 해당 인터페이스가 적용되면 평소처럼 여러 가지 측면을 적용합니다. 이 일을하는 또 다른 방법을 알아야 할 것 같은데요? –

+0

'FirstAspect' 커스텀 애트리뷰트의 존재 여부 확인은 어떻게 되나요? IInterface를 확인 하시겠습니까? 또는 도입 된 방법에 어떤면을 적용하고 싶습니까? –

답변

1

이 질문은 조금 오래된 것 같습니다. 그러나 나는 여전히 답을 필요로하는 비슷한 문제가 있습니다 (구현에 속성을 적용하고 복사하지 않고 도입 된 방법에 속성을 어떻게 도입합니까) . 즉, 내 자신의 질문을해야 할 수도 있습니다, 패턴에 대한 몇 가지 일반적인 단계가 당신의 딜레마를 해결할 수 있습니다 묻는거야,하지만 내 문제를 해결하지 않습니다. 이미이 중 일부를 실험 해본 것처럼 보입니다. 그러나 다른 사람들을 위해서는 자세히 설명하겠습니다.

요컨대, "반사"유형을 사용하여 종 류 종속성을 지정하지 마십시오. PostSharp는 애스펙트를 요구하거나 특정 순서를 요구하는 데 사용할 수있는 속성을 제공합니다 (개요는 Coping with Several Aspects on the Same Target 참조). 다른 애스펙트에 의해 이미 제공된 멤버를 가져 오는 메소드 (This StackOverflow Answer, 표시되지 않은 것은 올 바릅니다. 해당 사용자의 질문에 대한 대답과 함께 ImportMemberAttribute을 종별 의존성과 함께 사용하는 방법을 보여줍니다. ImportMemberAttribute은 주문이 올바른 한 다른 측면에서 회원을 가져올 수 있습니다. 이 속성에 대한 IsRequired 등록 정보는 구성원이 존재하지 않고 측면으로 소개되지 않은 경우 빌드 오류를 발생시킵니다.당신이 당신의 두 번째 측면은 인터페이스가 첫 번째 측면에 의해 적용 여부 여부, 인터페이스를 구현하는 모든 클래스에 적용 할 수 있도록하려면

이제, 당신은 AspectDependencyAction.OrderAspectTypeDependencyAttribute을 설정하지만, AspectTypeDependencyAttribute을 설정할 것 AspectDependencyAction.Required; 두 번째 측면을 첫 번째 관점에서 권고하는 대상에만 적용하려는 경우 여러 종속성 특성을 적용하여 요구 사항과 순서를 모두 지정할 수 있으며 Aspect Provider는 필요하지 않습니다 (위의 대답은 다중 하나의 화면에서 Pointcuts). 마찬가지로 첫 번째 요소에 항상 두 번째 요소가 필요한 경우 다른 방향으로 요구 사항을 지정하려면 AspectTypeDependencyAttribute을 추가로 적용 할 수 있습니다 (즉, 두 요소 모두 다른 요소를 요구할 경우 두 요소 모두에 요구 사항을 지정해야 함).

측면 "우선 순위"는 측면이 적용된 순서를 결정하는 데에도 사용할 수 있지만 가능하면 계약 문서로도 서버에 포함되기 때문에 종속성을 사용해야합니다.

이것은 사용자가 실제로 주문한 것을 의미하므로 사용자가 실제로 Aspect Provider를 사용할 필요가 없다고 가정합니다. 하나의 Aspect Provider가 다른 Aspect Provider의 결과에 의존하는 것을 원하지는 않을 것입니다. (이것은 관심의 분리를 위반할 것입니다.) 대신 각 대상에 대해 하나의 Aspect Provider yield을 가질 수 있습니다. 그러나 Aspect Providers에는 AspectTypeDependencyAttribute을 사용할 수도 있습니다. 예를 들어 유형 수준 애스펙트 제공자가 인터페이스를 소개하는 유형 수준 애스펙트를 주문한 다음 유형 및 유형에 대한 메소드를 루프 할 수있는 공급자를 가질 수 있습니다. 첫 번째 측면 (예 : 첫 번째 측면에서 도입 된 메서드를 호출 할 수있는 멤버에게 메서드 차단 조언을 적용하는 공급자에 의한 인터페이스 도입 추종자)에 의존하는 측면을 주입합니다.

희망 사항 (또는 질문이 제기 된 이후로 주어진 시간이 주어지면이 문제에 부딪히는 모든 사람)에게 도움이되는 호프입니다. 이 정보 중 일부는 구식이되거나 정확하지 않을 수도 있습니다 (일부 또는 모든 조건에서 aspect 제공자에게 전달 된 대상 유형에 주입 된 인터페이스를 탐지 할 수 있음). 그러나 표현 된 패턴은 여전히 PostSharp에서 제안한 선호 사례.