2017-02-01 1 views
3

someAttribute이라는 사용자 지정된 특성을 만들었습니다.
는 그것은 Skip 부울 부재 명명했다 다음 Main에서메서드 내에서 특성 '멤버를 사용하는 방법

public class someAttribute : Attribute 
{ 
    public bool Skip { get; set; } 
} 

나는 방법 foo()true와 부재 Skip 초기화.

다음 내가 함수 속성 [someAttribute()]을 가지고 foo()를 호출하고 있고 회원 Skip가 초기화 된 경우 내가 확인하려면 :

[someAttribute()] 
private static int foo() 
{ 
    if(Skip) 
    { 
     return 0; 
    } 

    return 1; 
} 

나는 오류 "이름을받은 '건너 뛰기'에 존재하지 않는 현재 컨텍스트 "입니다.
enter image description here

이 속성을 사용하는 메소드 내부의 속성 멤버를 어떻게 확인할 수 있습니까?

내 전체 코드 :

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Reflection; 

namespace ConsoleApplication1 
{ 
    class ProgramTest 
    { 
     [someAttribute()] 
     private static int foo() 
     { 
      if(Skip) 
      { 
       return 0; 
      } 

      return 1; 
     } 

     public class someAttribute : Attribute 
     { 
      public bool Skip { get; set; } 
     } 

     public static void initAttributes() 
     { 
      var methods = Assembly.GetExecutingAssembly().GetTypes().SelectMany(t => t.GetMethods(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static)) 
      .Where(method => Attribute.IsDefined(method, typeof(someAttribute))); 

      foreach (MethodInfo methodInfo in methods) 
      { 
       IEnumerable<someAttribute> SomeAttributes = methodInfo.GetCustomAttributes<someAttribute>(); 
       foreach (var attr in SomeAttributes) 
       { 
        attr.Skip = true; 
       } 
      } 
     } 
     static void Main(string[] args) 
     { 
      initAttributes(); 
      int num = foo(); 
     } 
    } 
} 

편집 :
나는 정적 기능 foo()를 얻을 수있는 refelction 위해서는 BindingFlags.Static을 추가했다.

+0

가능한 복제 [반사 - 재산에 이름과 속성 값을 얻을] (http://stackoverflow.com/questions/6637679/reflection-get-attribute-name-and-value-on-property) – HimBromBeere

+1

당신은'BindingFlags.Static | BindingFlags.NonPublic'은'foo' 메소드가'private static'입니다. – HimBromBeere

+0

코드를 편집하고 추가했습니다. 감사합니다. – E235

답변

1

: 그것은 static 때문에 그래서 당신은 또한해야, 당신은 Assembly.GetExecutingAssembly().GetTypes().SelectMany을 수행 할 때, 당신은 방법 foo를 얻을하지 않습니다 당신의 initAttributes() 방법,

[someAttribute()] 
private static int foo() 
{ 
    if (GetCurrentMethodAttribute<someAttribute>().Skip) 
    { 
     return 0; 
    } 
    return 1; 
} 

[MethodImpl(MethodImplOptions.NoInlining)] 
private static T GetCurrentMethodAttribute<T>() where T : Attribute 
{ 
    return (T)new StackTrace().GetFrame(1).GetMethod().GetCustomAttribute(typeof(T)); 
} 

어쨌든 BindingFlags.Static을 사용하십시오.

또한, you cannot set an attribute value at runtime, 그래서 변경 사항은 속성을 검색 할 때 "볼"수 없습니다 initAttributes (그렇게 될 것입니다 속성을 건너 뛰기 false)의

+0

런타임에 속성 속성을 설정하는 문제에 대해 Upvoted. 하지만 컴파일러가 메서드를 인라인하거나 다른 최적화로 인해 스택 추적 방법이 실패 할 수 있다고 생각합니다. –

1

이를 달성하기 위해 반사를 사용할 수 있습니다 그 방법은 someAttribute이있는 경우

[someAttribute()] 
private static int foo() 
{ 
    if (typeof(ProgramTest).GetMethod(nameof(foo)). 
         GetCustomAttribute<someAttribute>()?.Skip ?? false) 
     return 0; 

    return 1; 
} 

fooMethodInfo을 얻고 확인합니다. 그렇다면, 해당 속성 인스턴스의 Skip 특성을 점검합니다.

fooprivatestatic이기 때문에 GetMethod()에 더 많은 인수가 필요합니다. (: 이전 편집에서 나는 대신 ConditionalAttribute을 제안하지만, 분명히이 void 이외의 방법에 적용 할 수 없습니다 주)

private static int foo() 
{ 
    // some foo code 
    return 1; 
} 

[someAttribute(Skip=true)] 
private static int foo(int arg) 
{ 
    if (typeof(ProgramTest).GetMethod(nameof(foo), 
         BindingFlags.Static | BindingFlags.NonPublic, 
         null, // use default binder 
         new Type[] {typeof(int)}, // list of parameter types 
         null) // array of parameter modifiers 
       .GetCustomAttribute<someAttribute>()?.Skip ?? false) 
     return 0; 
    return arg; 
} 

을 : 당신이 foo의 여러 오버로드가있는 경우 당신은 또한 매개 변수 유형을 지정해야합니다.

당신이 뭔가에 속성을 얻을 수 있습니다