获取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
相关联的PropertyInfo(例如,通过typeof(Class1).GetProperty("Name")
),然后调用GetCustomAttributes
。
由于返回多个值,这有点麻烦 – 如果你需要从几个地方得到它,你可能要编写一个辅助方法来做到这一点。 (在某个框架中可能已经有了一个辅助方法,但是如果有的话我不知道)。
编辑:正如leppie指出的,有这样一个方法: Attribute.GetCustomAttribute(MemberInfo, Type)
首先,您需要获得一个表示该属性的MemberInfo
对象。 你需要做一些反思:
MemberInfo property = typeof(Class1).GetProperty("Name");
(我使用的是“旧式”reflection,但是如果您可以在编译时访问该types,也可以使用expression式树)
然后,您可以获取属性并获取DisplayName
属性的值:
var attribute = property.GetCustomAttributes(typeof(DisplayNameAttribute), true) .Cast<DisplayNameAttribute>().Single(); string displayName = attribute.DisplayName;
()括号是必需的错字错误
在具有Class1的视图中,因为它是强types的视图模型:
ModelMetadata.FromLambdaExpression<Class1, string>(x => x.Name, ViewData).DisplayName;
如果有人有兴趣从DisplayAttribute和ResourceType属性获取本地化string,如下所示:
[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();
Rich Tebb的好课堂! 我一直在使用DisplayAttribute,代码不适合我。 我唯一添加的是处理DisplayAttribute。 简单search得出这个属性是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; } } }
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(foo); foreach (PropertyDescriptor property in properties) { if (property.Name == "Name") { Console.WriteLine(property.DisplayName); //Something To Name } }
其中foo是Class1的一个实例
我有这个通用的实用方法。 我传入一个给定types的列表(假设你有一个支持类),它生成一个数据表,其中的属性是列标题,列表项是数据。
就像在标准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非常有用,因为EF将“导航”属性设置为虚拟。 但是,如果您select扩展这些类,它也会过滤掉您自己的任何虚拟属性。 出于这个原因,我更喜欢制作一个ViewModel,并根据需要只使用所需的属性和显示名称属性来装饰它,然后列出它们。
希望这可以帮助。
假设property
为PropertyInfo
types,可以在一行中完成:
property.GetCustomAttributes(typeof(DisplayNameAttribute), true).Cast<DisplayNameAttribute>().Single().DisplayName
下面的Rich Tebb和Matt Baker的回答,我想在一个linq查询中使用ReflectionExtensions方法,但它不起作用,所以我已经使这个方法工作:如果DisplayNameAttribute设置方法将返回它,否则将返回memberinfo名称:
testing方法:
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))); }
//testing方法输出:
//下面:具有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; }
试试这个代码:
EnumEntity.item.GetType().GetFields()[(int)EnumEntity.item].CustomAttributes.ToArray()[0].NamedArguments[0].TypedValue.ToString()
它会给你数据属性Name
的值。