public class Class1
{
[DisplayName("Something To Name")]
public virtual string Name { get; set; }
}
Comment obtenir la valeur de l'attribut DisplayName en C #?
Essayez ces méthodes utilitaires à moi:
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;
}
L'utilisation serait:
string displayName = ReflectionExtensions.GetPropertyDisplayName<SomeClass>(i => i.SomeProperty);
Vous devez obtenir le PropertyInfo
associé à la propriété (par exemple via typeof(Class1).GetProperty("Name")
), puis appeler GetCustomAttributes
.
C'est un peu compliqué à cause du retour de plusieurs valeurs - vous pouvez écrire une méthode d'assistance pour le faire si vous en avez besoin à plusieurs endroits. (Il se peut qu'il y ait déjà une méthode d'assistance dans le cadre quelque part, mais s'il n'y en a pas, je l'ignore.)
EDIT: Comme Leppie l’a fait remarquer, il existe une telle méthode : Attribute.GetCustomAttribute(MemberInfo, Type)
Tout d'abord, vous devez obtenir un objet MemberInfo
qui représente cette propriété. Vous devrez faire une forme de réflexion:
MemberInfo property = typeof(Class1).GetProperty("Name");
(J'utilise une réflexion "à l'ancienne", mais vous pouvez également utiliser un arbre d'expression si vous avez accès au type au moment de la compilation)
Ensuite, vous pouvez récupérer l'attribut et obtenir la valeur de la propriété DisplayName
:
var attribute = property.GetCustomAttributes(typeof(DisplayNameAttribute), true)
.Cast<DisplayNameAttribute>().Single();
string displayName = attribute.DisplayName;
() les parenthèses sont obligatoires faute de frappe
Si quelqu'un souhaite obtenir la chaîne localisée à partir de la propriété avec DisplayAttribute et ResourceType, comme ceci:
[Display(Name = "Year", ResourceType = typeof(ArrivalsResource))]
public int Year { get; set; }
Utilisez ce qui suit après displayAttribute != null
(comme indiqué ci-dessus par la réponse de @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();
Dans une vue ayant Class1 comme modèle de vue fortement typé:
ModelMetadata.FromLambdaExpression<Class1, string>(x => x.Name, ViewData).DisplayName;
De belles classes de Rich Tebb! J'utilise DisplayAttribute et le code ne fonctionne pas pour moi. La seule chose que j'ai ajoutée est la gestion de DisplayAttribute. Une brève recherche a révélé que cet attribut était nouveau dans MVC3 et .Net 4 et faisait presque la même chose et plus encore. Voici une version modifiée de la méthode:
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;
}
}
}
J'ai cette méthode d'utilité générique. Je passe dans une liste d'un type donné (en supposant que vous ayez une classe de support) et cela génère un datatable avec les propriétés comme en-tête de colonne et les éléments de liste comme données.
Tout comme dans MVC standard, si l'attribut DisplayName n'est pas défini, le nom de la propriété sera remplacé. Vous ne devez donc inclure que DisplayName s'il est différent du nom de la propriété.
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;
}
S'il existe un moyen plus efficace et plus sûr de le faire, j'apprécierais tout commentaire. La clause // Where commentée filtrera les propriétés virtuelles. Utile si vous utilisez directement des classes de modèle lorsque EF met dans les propriétés "Navigation" des propriétés virtuelles. Cependant, si vous choisissez d'étendre de telles classes, il filtrera également vos propres propriétés virtuelles. Pour cette raison, je préfère créer un ViewModel et le décorer avec uniquement les propriétés et les attributs de nom nécessaires, puis en dresser une liste.
J'espère que cela t'aides.
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(foo);
foreach (PropertyDescriptor property in properties)
{
if (property.Name == "Name")
{
Console.WriteLine(property.DisplayName); //Something To Name
}
}
où foo est une instance de Class1
var propInfo = new Class1().GetType().GetProperty("Name");
var displayNameAttribute = propInfo.GetCustomAttributes(typeof(DisplayNameAttribute), false);
var displayName = displayNameAttribute[0] as DisplayNameAttribute).DisplayName;
La variable displayName
contient maintenant la valeur de la propriété.
En supposant que property
soit de type PropertyInfo
, vous pouvez le faire en une seule ligne:
property.GetCustomAttributes(typeof(DisplayNameAttribute), true).Cast<DisplayNameAttribute>().Single().DisplayName
Essayez ce code:
EnumEntity.item.GetType().GetFields()[(int)EnumEntity.item].CustomAttributes.ToArray()[0].NamedArguments[0].TypedValue.ToString()
Cela vous donnera la valeur de l'attribut de données Name
.
suite à la réponse de Rich Tebb et Matt Baker, je voulais utiliser les méthodes ReflectionExtensions dans une requête linq mais cela n’a pas fonctionné, j’ai donc fait en sorte que cette méthode fonctionne: si DisplayNameAttribute est défini, elle le retournera sinon renvoyer le nom de membreinfo:
méthode d'essai:
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)));
}
// résultat de la méthode de test:
// ci-dessous: la classe avec l'attribut 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; }
}
// et la méthode d'extension:
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;
}
S'il vous plaît essayer ci-dessous le code, je pense que cela résoudra votre problème.
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);