2009-03-10 3 views
8

사용자 지정 속성을 사용하여 클래스 멤버가 양식 게시 (지불 게이트웨이)로 게시하기위한 속성에 매핑되는 방법을 정의합니다. 나는 잘 작동하는 커스텀 속성을 가지고 있고, "name"에 의해 속성을 얻을 수 있지만, 멤버 자체에 의해 속성을 얻고 싶습니다. 예를 들어클래스 멤버의 사용자 지정 속성

:

getFieldName("name"); 

계획은 postable 문자열로 회원들과 클래스를 직렬화하는 방법을 작성하는 것입니다

getFieldName(obj.Name); 

대. 사전에

foreach (MemberInfo i in (typeof(CustomClass)).GetMember("Name")) 
{ 
    foreach (object at in i.GetCustomAttributes(true)) 
    { 
     PropertyMapping map = at as PropertyMapping; 
     if (map != null) 
     { 
      ret += map.FieldName; 
     } 
    } 
} 

감사 :

여기 RET는 문자열이고 PropertyMapping 사용자 정의 속성입니다이 시점에서 내가 가지고있는 테스트 코드입니다!

+0

더 좋은 접근 방법이 있다면 나는 모든 귀입니다. – ccook

답변

9

: 코드의 사기 금액은 일반적인 접근 방식은 형식 변환기를 얻을 수도 있지만 여러 가지 방법이 PropertyDescriptor에 쉽게 Json.NET 등과 같은 직렬화 프레임 워크로 전환 C# 3.0을 사용하지 않는 한 LINQ (ehm, expression trees)에 의존해야합니다.

당신이하는 일은 컴파일러가 표현식 트리를 생성 할 수있게 해주는 람다 식에 대한 더미 메서드를 만드는 것입니다 (컴파일러는 형식 검사를 수행합니다). 그런 다음 그 나무를 파고 회원을 얻으십시오. 그래서 같이 :

static FieldInfo GetField<TType, TMemberType>(
    Expression<Func<TType, TMemberType>> accessor) 
{ 
    var member = accessor.Body as MemberExpression; 
    if (member != null) 
    { 
     return member.Member as FieldInfo; 
    } 
    return null; // or throw exception... 
} 

은 다음 클래스를 감안할 때 :

class MyClass 
{ 
    public int a; 
} 

당신은 메타 같은 데이터를 얻을 수 있습니다 : 당신이 다음 중 하나를 발굴 할 수있는 필드에 대한 참조

// get FieldInfo of member 'a' in class 'MyClass' 
var f = GetField((MyClass c) => c.a); 

을 평소와 같은 속성. 반사.

static TAttribute GetAttribute<TAttribute>( 
    this MemberInfo member) where TAttribute: Attribute 
{ 
    return member.GetCustomAttributes(typeof(TAttribute), false) 
     .Cast<TAttribute>().FirstOrDefault<TAttribute>(); 
} 

이제 모든 필드의 속성을 컴파일러가 확인한 내용으로 확인할 수 있습니다. 리팩토링에서도 작동합니다. 'a'라는 이름을 바꾸면 Visual Studio에서이를 인식합니다.

var attr = GetField((MyClass c) => c.a).GetAttribute<DisplayNameAttribute>(); 
Console.WriteLine(attr.DisplayName); 

해당 코드에는 하나의 리터럴 문자열이 없습니다.

+0

와우, 고마워요! 이것은 확실히 작동합니다, 나는 방금 그것을 테스트했습니다. 아주 좋은 :) – ccook

+0

답변으로 표시하는 것을 잊지 마세요;) –

+0

나는 return member.Member을 FieldInfo로 생각합니다. MemberInfo의 반환 유형이어야합니다. 그렇지 않은 경우는 항상 null가 반환됩니다. – Jeff

4

당신은 좀 더 간단하게의 절반을 수행 할 수 있습니다 BTW

foreach (PropertyMapping attrib in 
     Attribute.GetCustomAttributes(i, typeof(PropertyMapping))) 
    { 
     ret += map.FieldName; // whatever you want this to do... 
    } 

; 단어 Attribute으로 속성을 종료해야합니다. 이로 인해 중복이 발생하더라도 ([XmlAttributeAttribute] 참조).

그러나 다시 직렬화; 그것은 항상 사소한 것은 아닙니다. 당신은 정말 할 수 없습니다

foreach (PropertyDescriptor prop in TypeDescriptor.GetProperties(obj)) 
    { 
     Console.WriteLine("{0}={1}", 
      prop.Name, prop.Converter.ConvertToInvariantString(
       prop.GetValue(obj))); 
    } 
+0

Marc 님, 두 가지 변경 사항을 제안대로 채택했습니다 :) – ccook

+0

속성 설명자를 사용하는 것이 더 좋습니까? – ccook

+0

그것은 당신이하고있는 일에 달렸지 만, - PropertyDescriptor는 * 정확한 * 변환기 등을 얻는 것이 약간 더 쉽습니다. 그러나 대부분의면에서 그들은 비슷합니다. * xor *로 할 수있는 일이 있지만 대부분은 둘 중 하나에서 할 수 있습니다. –