获取DisplayName属性的值

时间:2011-02-16 11:26:53

标签: c# attributes

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

如何在C#中获取DisplayName属性的值?

16 个答案:

答案 0 :(得分:71)

尝试我的这些实用工具:

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);

答案 1 :(得分:29)

您需要获取与该媒体相关联的PropertyInfo(例如,通过typeof(Class1).GetProperty("Name")),然后拨打GetCustomAttributes

由于返回多个值,这有点乱 - 你可能想要编写一个帮助方法来执行此操作,如果你需要从几个地方。 (在某个框架中可能已经有一个帮助方法,但是如果我不知道它的话。)

编辑:正如leppie所指出的那样,这样一种方法:Attribute.GetCustomAttribute(MemberInfo, Type)

答案 2 :(得分:26)

首先,你需要获得一个代表该属性的MemberInfo对象。你需要做某种形式的反思:

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

(我正在使用“旧式”反射,但如果您在编译时可以访问该类型,也可以使用表达式树)

然后,您可以获取属性并获取DisplayName属性的值:

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

()括号是必需的拼写错误

答案 3 :(得分:12)

如果有人有兴趣从 DisplayAttribute ResourceType 获取属性中的本地化字符串,请执行以下操作:

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

displayAttribute != null之后使用以下内容(如@alex' answer所示):

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();

答案 4 :(得分:11)

在具有Class1的视图中,因为它是强类型视图模型:

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

答案 5 :(得分:6)

Rich Tebb的精彩课程! 我一直在使用DisplayAttribute,代码对我不起作用。我唯一添加的是处理DisplayAttribute。简短的搜索产生了这个属性对于MVC3&amp; .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;
            }
        }
    }

答案 6 :(得分:4)

我有这种通用的实用方法。我传入一个给定类型的列表(假设你有一个支持类),它生成一个数据表,其属性为列标题,列表项为数据。

就像在标准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;
    }

如果有更高效/更安全的方法,我会提供任何反馈意见。注释// Where子句将过滤掉虚拟属性。如果你直接使用模型类作为EF放入&#34;导航&#34;属性为虚拟。但是,如果您选择扩展此类,它也会过滤掉您自己的任何虚拟属性。出于这个原因,我更喜欢创建一个ViewModel并使用所需的属性和显示名称属性来装饰它,然后列出它们。

希望这有帮助。

答案 7 :(得分:3)

 PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(foo);

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

其中foo是Class1的实例

答案 8 :(得分:3)

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

displayName变量现在保存了该属性的值。

答案 9 :(得分:2)

迟到我认识的聚会。

我使用这个:

public static string GetPropertyDisplayName(PropertyInfo pi)
{
  var dp = pi.GetCustomAttributes(typeof(DisplayNameAttribute), true).Cast<DisplayNameAttribute>().SingleOrDefault();
  return dp != null ? dp.DisplayName : pi.Name;
}

希望这会有所帮助。

答案 10 :(得分:1)

假设propertyPropertyInfo类型,您可以在一行中执行此操作:

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

答案 11 :(得分:1)

试试这段代码:

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

它会为您提供数据属性Name的值。

答案 12 :(得分:0)

在Rich Tebb和Matt Baker的回答之后,我想在linq查询中使用ReflectionExtensions方法,但是它没有用,所以我已经使这个方法工作了:如果设置了DisplayNameAttribute,方法将返回它,否则它将返回memberinfo名称:

测试方法:

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

//下面:具有DisplayName属性的类

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; }
}

//和扩展方法:

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;

    }

答案 13 :(得分:0)

请尝试以下代码,我认为这可以解决您的问题。

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);
 }

答案 14 :(得分:0)

如果不是

[DisplayName(“要命名的东西”)]

您使用

[Display(Name =“名称的东西”)]

只需执行以下操作:

private string GetDisplayName(Class1 class1)
{
    string displayName = string.Empty;

    string propertyName = class1.Name.GetType().Name;

    CustomAttributeData displayAttribute = class1.GetType().GetProperty(propertyName).CustomAttributes.FirstOrDefault(x => x.AttributeType.Name == "DisplayAttribute");

    if (displayAttribute != null)
    {
        displayName = displayAttribute.NamedArguments.FirstOrDefault().TypedValue.Value;
    }

    return displayName;
}

答案 15 :(得分:0)

这有效,感谢上面的人:

foreach (PropertyInfo pi in properties)
{
    var propName = pi.Name;
    var dp = pi.GetCustomAttributes(typeof(DisplayNameAttribute), true).Cast<DisplayNameAttribute>().SingleOrDefault();
    if (dp != null)
    {
        propName = dp.DisplayName; 
    }
}