public class Class1
{
[DisplayName("Something To Name")]
public virtual string Name { get; set; }
}
如何在C#中获取DisplayName属性的值?
public class Class1
{
[DisplayName("Something To Name")]
public virtual string Name { get; set; }
}
如何在C#中获取DisplayName属性的值?
Answers:
尝试以下这些实用程序方法:
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);
首先,您需要获取一个MemberInfo
代表该属性的对象。您将需要进行某种形式的反思:
MemberInfo property = typeof(Class1).GetProperty("Name");
(我使用的是“旧式”反射,但是如果可以在编译时访问类型,则也可以使用表达式树)
然后,您可以获取属性并获取属性的值DisplayName
:
var attribute = property.GetCustomAttributes(typeof(DisplayNameAttribute), true)
.Cast<DisplayNameAttribute>().Single();
string displayName = attribute.DisplayName;
()括号是必需的拼写错误
您需要获取PropertyInfo
与该属性的关联(例如通过typeof(Class1).GetProperty("Name")
),然后调用GetCustomAttributes
。
由于返回多个值,因此有点混乱-如果您需要从几个地方开始,则可能需要编写一个辅助方法来执行此操作。(该框架中某处可能已经有一个辅助方法,但是如果存在,我将不知道。)
编辑:由于leppie指出的那样,是这样的方法:Attribute.GetCustomAttribute(MemberInfo, Type)
Attribute.GetCustomAttribute(MemberInfo, Type)
:) msdn.microsoft.com/en-us/library/ms130863
如果有人对使用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();
GetName()
方法仅返回Key,而不返回在资源文件中指定的Value。
.GetName()
,而不是上面的代码中,看到了问题,我与上面的代码在这里:stackoverflow.com/questions/43827360/...
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 = typeof(Class1).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;
}
如果有更有效/更安全的方法,我将不胜感激。带注释的// Where子句将滤除虚拟属性。如果您直接使用模型类,这很有用,因为EF将“ Navigation”属性以虚拟形式放置。但是,如果您选择扩展此类,它也会过滤掉您自己的任何虚拟属性。因此,我更喜欢制作一个ViewModel并仅用所需的属性来装饰它,并根据需要显示名称属性,然后列出它们。
希望这可以帮助。
我知道聚会晚了。
我用这个:
public static string GetPropertyDisplayName(PropertyInfo pi)
{
var dp = pi.GetCustomAttributes(typeof(DisplayNameAttribute), true).Cast<DisplayNameAttribute>().SingleOrDefault();
return dp != null ? dp.DisplayName : pi.Name;
}
希望这可以帮助。
假设property
是PropertyInfo
类型,您可以在一行中完成此操作:
property.GetCustomAttributes(typeof(DisplayNameAttribute), true).Cast<DisplayNameAttribute>().Single().DisplayName
请尝试以下代码,我认为这可以解决您的问题。
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);
}
遵循Rich Tebb和Matt Baker的回答,我想ReflectionExtensions
在LINQ查询中使用这些方法,但是它不起作用,因此我使这种方法起作用。
如果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)));
}
测试方法输出:
具有DisplayName1
属性的类:
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;
}
如果相反
[DisplayName(“要命名的东西”)]
你用
[显示(名称=“名称的东西”)]
只是这样做:
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;
}