program story

DisplayName 속성 값 가져 오기

inputbox 2020. 11. 26. 08:15
반응형

DisplayName 속성 값 가져 오기


public class Class1
{
    [DisplayName("Something To Name")]
    public virtual string Name { get; set; }
}

C #에서 DisplayName 특성 값을 얻는 방법은 무엇입니까?


내 유틸리티 방법을 시도하십시오.

using System.ComponentModel;
using System.Globalization;
using System.Linq;


public static T GetAttribute<T>(this MemberInfo member, bool isRequired)
    where T : Attribute
{
    var attribute = member.GetCustomAttributes(typeof(T), false).SingleOrDefault();

    if (attribute == null && isRequired)
    {
        throw new ArgumentException(
            string.Format(
                CultureInfo.InvariantCulture, 
                "The {0} attribute must be defined on member {1}", 
                typeof(T).Name, 
                member.Name));
    }

    return (T)attribute;
}

public static string GetPropertyDisplayName<T>(Expression<Func<T, object>> propertyExpression)
{
    var memberInfo = GetPropertyInformation(propertyExpression.Body);
    if (memberInfo == null)
    {
        throw new ArgumentException(
            "No property reference expression was found.",
            "propertyExpression");
    }

    var attr = memberInfo.GetAttribute<DisplayNameAttribute>(false);
    if (attr == null)
    {
        return memberInfo.Name;
    }

    return attr.DisplayName;
}

public static MemberInfo GetPropertyInformation(Expression propertyExpression)
{
    Debug.Assert(propertyExpression != null, "propertyExpression != null");
    MemberExpression memberExpr = propertyExpression as MemberExpression;
    if (memberExpr == null)
    {
        UnaryExpression unaryExpr = propertyExpression as UnaryExpression;
        if (unaryExpr != null && unaryExpr.NodeType == ExpressionType.Convert)
        {
            memberExpr = unaryExpr.Operand as MemberExpression;
        }
    }

    if (memberExpr != null && memberExpr.Member.MemberType == MemberTypes.Property)
    {
        return memberExpr.Member;
    }

    return null;
}

사용법은 다음과 같습니다.

string displayName = ReflectionExtensions.GetPropertyDisplayName<SomeClass>(i => i.SomeProperty);

당신은하는 데 필요한 PropertyInfo재산으로 (예를 통해 관련된 typeof(Class1).GetProperty("Name")) 다음 호출 GetCustomAttributes.

여러 값을 반환하기 때문에 약간 지저분합니다. 필요한 경우 몇 군데에서이를 수행하는 도우미 메서드를 작성하는 것이 좋습니다. (프레임 워크 어딘가에 이미 도우미 메서드가있을 수 있지만있는 경우에는 알 수 없습니다.)

편집 : leppie가 지적했듯이, 거기 이다 그런 방법 :Attribute.GetCustomAttribute(MemberInfo, Type)


먼저 MemberInfo해당 속성을 나타내는 개체를 가져와야합니다. 당신은 어떤 형태의 반성을해야 할 것입니다 :

MemberInfo property = typeof(Class1).GetProperty("Name");

(저는 "이전 스타일"리플렉션을 사용하고 있지만 컴파일 타임에 유형에 액세스 할 수있는 경우 표현식 트리를 사용할 수도 있습니다.)

그런 다음 속성을 가져오고 속성 값을 가져올 수 있습니다 DisplayName.

var attribute = property.GetCustomAttributes(typeof(DisplayNameAttribute), true)
      .Cast<DisplayNameAttribute>().Single();
string displayName = attribute.DisplayName;

() 괄호는 필수 입력 오류입니다.


강력한 형식의 뷰 모델이므로 Class1이있는 뷰 내에서 :

ModelMetadata.FromLambdaExpression<Class1, string>(x => x.Name, ViewData).DisplayName;

다음 같이 DisplayAttributeResourceType 을 사용하여 속성에서 지역화 된 문자열을 가져 오는 데 관심이있는 사람이있는 경우 :

[Display(Name = "Year", ResourceType = typeof(ArrivalsResource))]
public int Year { get; set; }

뒤에 다음을 사용하십시오 displayAttribute != null(위에서 @alex의 답변으로 표시됨).

ResourceManager resourceManager = new ResourceManager(displayAttribute.ResourceType);
var entry = resourceManager.GetResourceSet(Thread.CurrentThread.CurrentUICulture, true, true)
                           .OfType<DictionaryEntry>()
                           .FirstOrDefault(p => p.Key.ToString() == displayAttribute.Name);

return entry.Value.ToString();

Rich Tebb의 멋진 수업! DisplayAttribute를 사용해 왔지만 코드가 작동하지 않았습니다. 내가 추가 한 유일한 것은 DisplayAttribute 처리입니다. 간략한 검색 결과이 속성은 MVC3 및 .Net 4의 새로운 기능이며 거의 동일한 기능을 더하는 것으로 나타났습니다. 다음은 메서드의 수정 된 버전입니다.

 public static string GetPropertyDisplayString<T>(Expression<Func<T, object>> propertyExpression)
    {
        var memberInfo = GetPropertyInformation(propertyExpression.Body);
        if (memberInfo == null)
        {
            throw new ArgumentException(
                "No property reference expression was found.",
                "propertyExpression");
        }

        var displayAttribute = memberInfo.GetAttribute<DisplayAttribute>(false);

        if (displayAttribute != null)
        {
            return displayAttribute.Name;
        }
        else
        {
            var displayNameAttribute = memberInfo.GetAttribute<DisplayNameAttribute>(false);
            if (displayNameAttribute != null)
            {
                return displayNameAttribute.DisplayName;
            }
            else
            {
                return memberInfo.Name;
            }
        }
    }

var propInfo = new Class1().GetType().GetProperty("Name");
var displayNameAttribute = propInfo.GetCustomAttributes(typeof(DisplayNameAttribute), false);
var displayName = displayNameAttribute[0] as DisplayNameAttribute).DisplayName;

displayName 변수는 이제 속성의 값을 보유합니다.


이 일반적인 유틸리티 방법이 있습니다. 주어진 유형의 목록 (지원 클래스가 있다고 가정)을 전달하고 속성이있는 데이터 테이블을 열 머리글로, 목록 항목을 데이터로 생성합니다.

표준 MVC와 마찬가지로 DisplayName 속성이 정의되어 있지 않으면 속성 이름으로 대체되므로 속성 이름과 다른 DisplayName 만 포함하면됩니다.

    public DataTable BuildDataTable<T>(IList<T> data)
    {
        //Get properties
        PropertyInfo[] Props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
        //.Where(p => !p.GetGetMethod().IsVirtual && !p.GetGetMethod().IsFinal).ToArray(); //Hides virtual properties

        //Get column headers
        bool isDisplayNameAttributeDefined = false;
        string[] headers = new string[Props.Length];
        int colCount = 0;
        foreach (PropertyInfo prop in Props)
        {
            isDisplayNameAttributeDefined = Attribute.IsDefined(prop, typeof(DisplayNameAttribute));

            if (isDisplayNameAttributeDefined)
            {
                DisplayNameAttribute dna = (DisplayNameAttribute)Attribute.GetCustomAttribute(prop, typeof(DisplayNameAttribute));
                if (dna != null)
                    headers[colCount] = dna.DisplayName;
            }
            else
                headers[colCount] = prop.Name;

            colCount++;
            isDisplayNameAttributeDefined = false;
        }

        DataTable dataTable = new DataTable(typeof(T).Name);

        //Add column headers to datatable
        foreach (var header in headers)
            dataTable.Columns.Add(header);

        dataTable.Rows.Add(headers);

        //Add datalist to datatable
        foreach (T item in data)
        {
            object[] values = new object[Props.Length];
            for (int col = 0; col < Props.Length; col++)
                values[col] = Props[col].GetValue(item, null);

            dataTable.Rows.Add(values);
        }

        return dataTable;
    }

If there's a more efficient / safer way of doing this, I'd appreicate any feedback. The commented //Where clause will filter out virtual properties. Useful if you are using model classes directly as EF puts in "Navigation" properties as virtual. However it will also filter out any of your own virtual properties if you choose to extend such classes. For this reason, I prefer to make a ViewModel and decorate it with only the needed properties and display name attributes as required, then make a list of them.

Hope this helps.


PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(foo);

foreach (PropertyDescriptor property in properties)
{
    if (property.Name == "Name")
    {
        Console.WriteLine(property.DisplayName); // Something To Name
    }
}

where foo is an instance of Class1


Assuming property as PropertyInfo type, you can do this in one single line:

property.GetCustomAttributes(typeof(DisplayNameAttribute), true).Cast<DisplayNameAttribute>().Single().DisplayName

Try this code:

EnumEntity.item.GetType().GetFields()[(int)EnumEntity.item].CustomAttributes.ToArray()[0].NamedArguments[0].TypedValue.ToString()

It will give you the value of data attribute Name.


Please try below code, I think this will solve your problem.

var classObj = new Class1();
classObj.Name => "StackOverflow";

var property = new Class1().GetType().GetProperty(nameof(classObj.Name));
var displayNameAttributeValue = (property ?? throw new InvalidOperationException())
    .GetCustomAttributes(typeof(DisplayNameAttribute)) as DisplayNameAttribute; 

if (displayNameAttributeValue != null)
{
   Console.WriteLine("{0} = {1}", displayNameAttributeValue, classObj.Name);
}

Following Rich Tebb's and Matt Baker's answer, I wanted to use the ReflectionExtensions methods in a LINQ query, but it didn't work, so I've made this method for it to work.

If DisplayNameAttribute is set the method will return it, otherwise it will return the MemberInfo name.

Test method:

static void Main(string[] args)
{
    var lst = new List<Test>();
    lst.Add(new Test("coucou1", "kiki1"));
    lst.Add(new Test("coucou2", "kiki2"));
    lst.Add(new Test("coucou3", "kiki3"));
    lst.Add(new Test("coucou4", "kiki4"));
    lst.ForEach(i => 
        Console.WriteLine(i.GetAttributeName<Test>(t => t.Name) + ";" + i.GetAttributeName<Test>(t=>t.t2)));
}

Test method output:

Test method output

The class with DisplayName1 Attribute:

public class Test
{
    public Test() { }
    public Test(string name, string T2)
    {
        Name = name;
        t2 = T2;
    }
    [DisplayName("toto")]
    public string Name { get; set; }
    public string t2 { get; set; }
}

And the extension method:

public static string GetAttributeName<T>(this T itm, Expression<Func<T, object>> propertyExpression)
{
    var memberInfo = GetPropertyInformation(propertyExpression.Body);
    if (memberInfo == null)
    {
        throw new ArgumentException(
            "No property reference expression was found.",
            "propertyExpression");
    }

    var pi = typeof(T).GetProperty(memberInfo.Name);
    var ret = pi.GetCustomAttributes(typeof(DisplayNameAttribute), true).Cast<DisplayNameAttribute>().SingleOrDefault();
    return ret != null ? ret.DisplayName : pi.Name;

}

참고URL : https://stackoverflow.com/questions/5015830/get-the-value-of-displayname-attribute

반응형