Probieren Sie meine Dienstprogrammmethoden aus:
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;
}
Verwendung wäre:
string displayName = ReflectionExtensions.GetPropertyDisplayName<SomeClass>(i => i.SomeProperty);
Zunächst müssen Sie ein
MemberInfo
Objekt abrufen, das diese Eigenschaft darstellt. Sie müssen irgendeine Form der Reflexion machen:MemberInfo property = typeof(Class1).GetProperty("Name");
(Ich verwende die Reflexion im "alten Stil", aber Sie können auch einen Ausdrucksbaum verwenden, wenn Sie zur Kompilierungszeit Zugriff auf den Typ haben.)
Dann können Sie das Attribut abrufen und den Wert der
DisplayName
Eigenschaft erhalten:var attribute = property.GetCustomAttributes(typeof(DisplayNameAttribute), true) .Cast<DisplayNameAttribute>().Single(); string displayName = attribute.DisplayName;
() Klammern sind Tippfehler erforderlich
quelle
Sie müssen die
PropertyInfo
mit der Eigenschaft verknüpfte (z. B. viatypeof(Class1).GetProperty("Name")
) abrufen und dann anrufenGetCustomAttributes
.Es ist etwas chaotisch, weil mehrere Werte zurückgegeben werden. Möglicherweise möchten Sie eine Hilfsmethode schreiben, um dies zu tun, wenn Sie sie an einigen Stellen benötigen. (Möglicherweise gibt es bereits irgendwo eine Hilfsmethode im Framework, aber wenn ja, weiß ich nichts davon.)
EDIT: Wie Leppie betonte, gibt es eine solche Methode:
Attribute.GetCustomAttribute(MemberInfo, Type)
quelle
Attribute.GetCustomAttribute(MemberInfo, Type)
:) msdn.microsoft.com/en-us/library/ms130863In einer Ansicht mit Class1 als stark typisiertem Ansichtsmodell:
ModelMetadata.FromLambdaExpression<Class1, string>(x => x.Name, ViewData).DisplayName;
quelle
Wenn jemand daran interessiert ist, die lokalisierte Zeichenfolge mit DisplayAttribute und ResourceType wie folgt aus der Eigenschaft abzurufen :
[Display(Name = "Year", ResourceType = typeof(ArrivalsResource))] public int Year { get; set; }
Verwenden Sie nachfolgend Folgendes
displayAttribute != null
(wie oben in der Antwort von @alex gezeigt ):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();
quelle
DisplayAttribute
hatGetName
Methode. Ihr Code in .NET 4+ ist nicht erforderlichGetName()
Methode nur den Schlüssel und nicht den in der Ressourcendatei angegebenen Wert zurück..GetName()
anstelle des obigen Codes zu verwenden, siehe das Problem, das ich mit dem obigen Code hier hatte: stackoverflow.com/questions/43827360/…Schöne Klassen von Rich Tebb! Ich habe DisplayAttribute verwendet und der Code hat bei mir nicht funktioniert. Das einzige, was ich hinzugefügt habe, ist die Handhabung von DisplayAttribute. Eine kurze Suche ergab, dass dieses Attribut für MVC3 & .Net 4 neu ist und fast dasselbe und noch mehr bewirkt. Hier ist eine modifizierte Version der Methode:
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; } } }
quelle
var propInfo = typeof(Class1).GetProperty("Name"); var displayNameAttribute = propInfo.GetCustomAttributes(typeof(DisplayNameAttribute), false); var displayName = (displayNameAttribute[0] as DisplayNameAttribute).DisplayName;
displayName
Variable enthält jetzt den Wert der Eigenschaft.quelle
Ich habe diese generische Dienstprogrammmethode. Ich übergebe eine Liste eines bestimmten Typs (vorausgesetzt, Sie haben eine unterstützende Klasse) und sie generiert eine Datentabelle mit den Eigenschaften als Spaltenüberschriften und den Listenelementen als Daten.
Wenn Sie wie in Standard-MVC kein DisplayName-Attribut definiert haben, wird auf den Eigenschaftsnamen zurückgegriffen, sodass Sie DisplayName nur dort einfügen müssen, wo es sich vom Eigenschaftsnamen unterscheidet.
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; }
Wenn es einen effizienteren / sichereren Weg gibt, würde ich jedes Feedback begrüßen. Die kommentierte // Where-Klausel filtert virtuelle Eigenschaften heraus. Nützlich, wenn Sie Modellklassen direkt verwenden, da EF die Eigenschaften "Navigation" als virtuell einfügt. Es werden jedoch auch Ihre eigenen virtuellen Eigenschaften herausgefiltert, wenn Sie solche Klassen erweitern. Aus diesem Grund ziehe ich es vor, ein ViewModel zu erstellen und es nach Bedarf nur mit den erforderlichen Eigenschaften und Anzeigenamenattributen zu dekorieren und dann eine Liste davon zu erstellen.
Hoffe das hilft.
quelle
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(foo); foreach (PropertyDescriptor property in properties) { if (property.Name == "Name") { Console.WriteLine(property.DisplayName); // Something To Name } }
Wo
foo
ist eine Instanz vonClass1
quelle
Spät zur Party, die ich kenne.
Ich benutze das:
public static string GetPropertyDisplayName(PropertyInfo pi) { var dp = pi.GetCustomAttributes(typeof(DisplayNameAttribute), true).Cast<DisplayNameAttribute>().SingleOrDefault(); return dp != null ? dp.DisplayName : pi.Name; }
Hoffe das hilft.
quelle
Angenommen,
property
alsPropertyInfo
Typ können Sie dies in einer einzigen Zeile tun:property.GetCustomAttributes(typeof(DisplayNameAttribute), true).Cast<DisplayNameAttribute>().Single().DisplayName
quelle
Versuchen Sie diesen Code:
EnumEntity.item.GetType().GetFields()[(int)EnumEntity.item].CustomAttributes.ToArray()[0].NamedArguments[0].TypedValue.ToString()
Sie erhalten den Wert des Datenattributs
Name
.quelle
Bitte versuchen Sie es mit dem folgenden Code. Ich denke, dies wird Ihr Problem lösen.
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); }
quelle
Nach der Antwort von Rich Tebb und Matt Baker wollte ich die
ReflectionExtensions
Methoden in einer LINQ-Abfrage verwenden, aber es hat nicht funktioniert, also habe ich diese Methode so gemacht, dass sie funktioniert.Wenn
DisplayNameAttribute
festgelegt, gibt die Methode es zurück, andernfalls wird derMemberInfo
Name zurückgegeben.Testmethode:
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))); }
Ausgabe der Testmethode:
Die Klasse mit
DisplayName1
Attribut: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; } }
Und die Erweiterungsmethode:
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;
}}
quelle
GetPropertyInformation()
existiert in diesem Zusammenhang nicht. Ich habe gerade festgestellt, dass dieser Code in einer Antwort unten vorhanden istWenn stattdessen
Sie verwenden
Mach das einfach:
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; }
quelle