[C#] 반영-속성의 속성 이름 및 값 가져 오기

수업이 있는데 이름이라는 속성으로 Book이라고 부릅니다. 해당 속성과 관련된 속성이 있습니다.

public class Book
{
    [Author("AuthorName")]
    public string Name
    {
        get; private set;
    }
}

내 주요 방법에서 리플렉션을 사용하고 있으며 각 속성에 대한 각 속성의 키 값 쌍을 가져 오려고합니다. 따라서이 예에서는 속성 이름으로 “Author”가 표시되고 속성 값으로 “AuthorName”이 표시됩니다.

질문 : Reflection을 사용하여 속성의 속성 이름과 값을 얻으려면 어떻게합니까?



답변

인스턴스 typeof(Book).GetProperties()배열을 얻는 데 사용 PropertyInfo합니다. 그런 다음 GetCustomAttributes()각각 PropertyInfo을 사용 하여 Author속성 유형 이 있는지 확인하십시오 . 그렇다면 속성 정보에서 속성 이름을, 속성에서 속성 값을 얻을 수 있습니다.

특정 속성 유형이있는 특성의 유형을 스캔하고 사전에 데이터를 리턴하기 위해 다음 행을 따라야합니다 (유형을 루틴에 전달하여 더 동적으로 만들 수 있음).

public static Dictionary<string, string> GetAuthors()
{
    Dictionary<string, string> _dict = new Dictionary<string, string>();

    PropertyInfo[] props = typeof(Book).GetProperties();
    foreach (PropertyInfo prop in props)
    {
        object[] attrs = prop.GetCustomAttributes(true);
        foreach (object attr in attrs)
        {
            AuthorAttribute authAttr = attr as AuthorAttribute;
            if (authAttr != null)
            {
                string propName = prop.Name;
                string auth = authAttr.Name;

                _dict.Add(propName, auth);
            }
        }
    }

    return _dict;
}


답변

사전에서 속성의 모든 속성을 얻으려면 다음을 사용하십시오.

typeof(Book)
  .GetProperty("Name")
  .GetCustomAttributes(false)
  .ToDictionary(a => a.GetType().Name, a => a);

에서 변경해야 false하는 true당신이 아니라 inheritted 특성을 포함 할 경우.


답변

하나의 특정 속성 값만 원하면 디스플레이 속성과 같이 다음 코드를 사용할 수 있습니다.

var pInfo = typeof(Book).GetProperty("Name")
                             .GetCustomAttribute<DisplayAttribute>();
var name = pInfo.Name;


답변

Generic Extension Property Attribute Helper를 작성하여 비슷한 문제를 해결했습니다.

using System;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;

public static class AttributeHelper
{
    public static TValue GetPropertyAttributeValue<T, TOut, TAttribute, TValue>(
        Expression<Func<T, TOut>> propertyExpression,
        Func<TAttribute, TValue> valueSelector)
        where TAttribute : Attribute
    {
        var expression = (MemberExpression) propertyExpression.Body;
        var propertyInfo = (PropertyInfo) expression.Member;
        var attr = propertyInfo.GetCustomAttributes(typeof(TAttribute), true).FirstOrDefault() as TAttribute;
        return attr != null ? valueSelector(attr) : default(TValue);
    }
}

용법:

var author = AttributeHelper.GetPropertyAttributeValue<Book, string, AuthorAttribute, string>(prop => prop.Name, attr => attr.Author);
// author = "AuthorName"


답변

당신은 사용할 수 있습니다 GetCustomAttributesData()GetCustomAttributes():

var attributeData = typeof(Book).GetProperty("Name").GetCustomAttributesData();
var attributes = typeof(Book).GetProperty("Name").GetCustomAttributes(false);


답변

“하나의 매개 변수를 사용하는 속성의 경우 attribute-names 및 parameter-value를 나열하십시오”를 의미하는 경우 CustomAttributeDataAPI 를 통해 .NET 4.5에서 더 쉽습니다 .

using System.Collections.Generic;
using System.ComponentModel;
using System.Reflection;

public static class Program
{
    static void Main()
    {
        PropertyInfo prop = typeof(Foo).GetProperty("Bar");
        var vals = GetPropertyAttributes(prop);
        // has: DisplayName = "abc", Browsable = false
    }
    public static Dictionary<string, object> GetPropertyAttributes(PropertyInfo property)
    {
        Dictionary<string, object> attribs = new Dictionary<string, object>();
        // look for attributes that takes one constructor argument
        foreach (CustomAttributeData attribData in property.GetCustomAttributesData())
        {

            if(attribData.ConstructorArguments.Count == 1)
            {
                string typeName = attribData.Constructor.DeclaringType.Name;
                if (typeName.EndsWith("Attribute")) typeName = typeName.Substring(0, typeName.Length - 9);
                attribs[typeName] = attribData.ConstructorArguments[0].Value;
            }

        }
        return attribs;
    }
}

class Foo
{
    [DisplayName("abc")]
    [Browsable(false)]
    public string Bar { get; set; }
}


답변

private static Dictionary<string, string> GetAuthors()
{
    return typeof(Book).GetProperties()
        .SelectMany(prop => prop.GetCustomAttributes())
        .OfType<AuthorAttribute>()
        .ToDictionary(attribute => attribute.Name, attribute => attribute.Name);
}