2017-03-01 2 views
1

내가 제네릭 클래스를 가지고 말? 그래서 같이 ithe의 AssemblyInfo.cs에 측면을 추가하고있다 : 선언적인 방법으로 필터링 일반적인 인수를 적용 할 수 없습니다일반 클래스의 특정 구현에서 애스펙트를 제외 하시겠습니까?</p>이 <pre><code>public abstract class MyClass<T> { // Contents } </code></pre> <p>어떻게 내가이 T의 특정 유형의 내 측면에 대한 제외 지정할 수 있습니다

[assembly: LogMethod(AttributePriority = 0, 
        AttributeTargetTypeAttributes = MulticastAttributes.Public, 
        AttributeTargetMemberAttributes = MulticastAttributes.Public, 
        AttributeTargetElements = MulticastTargets.Method)] 

답변

1

. 애스펙트 타겟의 고급 필터링의 경우 애스펙트에서 CompileTimeValidate 메소드를 오버라이드하고 프로그래밍 방식으로 필터링 할 수 있습니다.

그러나 설명 된 경우에도이 정도면 충분하지 않습니다. 메서드에 애스펙트를 MyClass<T>에 적용했다고 가정 해 보겠습니다. 컴파일 시점에 T는 아직 알려지지 않았으므로 검사를 수행 할 수 없습니다. 구체적인 T는 MyClass<T>의 필드 또는 변수가 코드의 다른 곳에서 선언 될 때 알려져 있습니다.

가장 좋은 옵션은 어프로치를 instance-scoped으로 만들고 대상 클래스의 각 인스턴스에 대해 런타임에 유효성을 검사하는 것입니다. 아래에서이 접근법의 샘플 구현을 찾을 수 있습니다.

[PSerializable] 
public class LogMethodAttribute : OnMethodBoundaryAspect, IInstanceScopedAspect 
{ 
    private bool disabled; 

    public override void OnEntry(MethodExecutionArgs args) 
    { 
     if (!this.disabled) 
     { 
      Console.WriteLine("OnEntry: {0}({1})", args.Method.Name, args.Arguments.GetArgument(0)); 
     } 
    } 

    public object CreateInstance(AdviceArgs adviceArgs) 
    { 
     LogMethodAttribute clone = (LogMethodAttribute) this.MemberwiseClone(); 

     Type type = adviceArgs.Instance.GetType(); 
     if (type.IsGenericType) 
     { 
      Type[] genericArguments = type.GetGenericArguments(); 
      // Filter out targets where T is string. 
      if (genericArguments[0] == typeof(string)) 
      { 
       clone.disabled = true; 
      } 
     } 

     return clone; 
    } 

    public void RuntimeInitializeInstance() 
    { 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     var obj1 = new Class1<int>(); 
     obj1.Method1(1); 

     var obj2 = new Class1<string>(); 
     obj2.Method1("a"); 
    } 
} 

[LogMethod(AttributeTargetElements = MulticastTargets.Method)] 
public class Class1<T> 
{ 
    public void Method1(T a) 
    { 
    } 
}