2013-03-25 2 views
1

확장 메서드를 사용하여 클래스 멤버 (필드 전용)의 사용자 지정 특성을 확인하려고합니다.확장 메서드를 사용하여 필드의 특성에 액세스

public class DatabaseIdAttribute : Attribute 
{ 
    public int ID { get; set; } 

    public DatabaseIdAttribute(int id) 
    { 
     this.ID = id; 
    } 
} 

public class MyClass 
{ 
    [DatabaseId(1)] 
    double Height {get;set;} 

    [DatabaseId(2)] 
    double Width {get;set;} 

    double Area { get { return this.Height * this.Width; } 
} 

마법 필드를 전달하는 대신 클래스 필드에 액세스하려면 확장 메서드에서 LINQ 식을 사용하고 싶습니다.

var myClass = new MyClass(); 
var attribute = myClass.GetAttribute<DatabaseIdAttribute>(c => c.Height); 

달성 할 수 있습니까? 시간에 대한

[편집]

, 나는 @leppie 다음과 같은 방법으로

var c = new MyClass(); 
var attribute = c.GetMember(m => m.Height).GetAttribute<DatabaseIdAttribute>(); 
의 속성을 얻을 수 있습니다

public static MemberInfo GetMember<T, R>(this T instance, Expression<Func<T, R>> selector) 
    { 
     var member = selector.Body as MemberExpression; 
     if (member != null) 
     { 
      return member.Member; 
     } 
     return null; 
    } 

    public static T GetAttribute<T>(this MemberInfo member) where T : Attribute 
    { 
     return member.GetCustomAttributes(false).OfType<T>().SingleOrDefault(); 
    } 

의 도움으로 다음 달성되는

하지만 다음과 같은 방법으로 액세스 할 수 있기를 바랍니다.

var c = new MyClass(); 
var attribute = c.GetAttribute<DatabaseIdAttribute>(m => m.Height); 
+2

네, 가능하고, 사소한입니다. 너 뭐 해봤 니? – leppie

+0

예, 사소한 것처럼 보이지만 예제를 찾을 수 없습니다. 그래서 내가 여기 물었습니다. –

+0

'object'를 사용하지 마십시오. 그렇지 않으면 변환이 수반됩니다. 추가 일반 매개 변수 (예 :'R')를 사용하십시오. 또한, 멤버는 'PropertyInfo'일 수도 있습니다 (이 경우). 'MemberInfo'는 속성에만 관심이 있다면 여기에서 충분할 것입니다. – leppie

답변

4

거의 다 왔어! 이것은 (안된다) 작동해야합니다.

public static class ObjectExtensions 
{ 
    public static MemberInfo GetMember<T,R>(this T instance, 
     Expression<Func<T, R>> selector) 
    { 
     var member = selector.Body as MemberExpression; 
     if (member != null) 
     { 
      return member.Member; 
     } 
     return null; 
    } 

    public static T GetAttribute<T>(this MemberInfo meminfo) where T : Attribute 
    { 
     return meminfo.GetCustomAttributes(typeof(T)).FirstOrDefault() as T; 
    } 
} 

사용법 :

var attr = someobject.GetMember(x => x.Height). 
       GetAttribute<DatabaseIdAttribute>(); 

IIRC : GetAttribute<T>(this MemberInfo meminfo) 이미 .NET에서 확장 메서드로 정의 4.

+0

내가 잘못하지 않았다면이 메서드를 호출하기 위해 세 개의 매개 변수가 필요합니다. 이 무언가를 찾고 있었어 var myClass = new MyClass(); var attribute = myClass.GetAttribute (c => c.Height); –

+0

@RK : AFAIK, 네 말이 맞아. 당신은 그것을 돕기 위해 유창하게 만들 수 있습니다. 답변을 수정할 것입니다. – leppie

+0

.NET 4.5라고 생각합니다. 그러나 나는 또한 확실하지 않다. –

1

당신이 여분의 일반적인 유형을 공급 괜찮다면, 당신은 할 수있다 이 :

public static class ReflectionHelper 
{ 
    public static TAttr GetAttribute<TClass, TProp, TAttr>(Expression<Func<TClass, TProp>> selector) where TAttr : Attribute 
    { 
     var member = selector.Body as MemberExpression; 
     return member.Member.GetCustomAttributes<TAttr>(false).First(); 
    } 
} 

그런 다음 당신은 다음과 같이 사용할 수 있습니다 :

var attribute = ReflectionHelper.GetAttribute<MyClass, double, DatabaseIdAttribute>(m => m.Height); 

이것은 확장 메서드가 아니기 때문에 (정적 확장을 사용할 수 없음) 클래스의 인스턴스를 만들 필요가 없습니다. 그렇게 같이 호출 할 것이다

public static TAttr GetAttribute<TClass, TProp, TAttr>(this TClass instance, Expression<Func<TClass, TProp>> selector) where TAttr : Attribute 
{ 
    var member = selector.Body as MemberExpression; 
    return member.Member.GetCustomAttributes<TAttr>(false).First(); 
} 

:

은 물론 여전히 확장 메서드 버전 가질 수

var c = new MyClass(); 
var attribute = c.GetAttribute<MyClass, double, DatabaseIdAttribute>(m => m.Height); 

을하지만 어느 쪽이든은 매우 상세하다. 당신이 컴파일이 일반 모든 유형을 추론하려는 경우, 우리는 우리의 속성의 인스턴스를 전달해야 할 것 :

public static class ReflectionHelper 
{ 
    public static TAttr GetAttribute<TClass, TProp, TAttr>(TAttr attribute, Expression<Func<TClass, TProp>> selector) where TAttr : Attribute 
    { 
     var member = selector.Body as MemberExpression; 
     return member.Member.GetCustomAttributes<TAttr>(false).First(); 
    } 
} 

사용법 :

var attribute = ReflectionHelper.GetAttribute(new DatabaseIdAttribute(), m => m.Height); 
관련 문제