Get the Value of Displayname Attribute

get the value of DisplayName attribute

Try these utility methods of mine:

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

Usage would be:

string displayName = ReflectionExtensions.GetPropertyDisplayName<SomeClass>(i => i.SomeProperty);

How to get the Value in [Display(Name= )] attribute in Controller for any property using EF6

This should work:

MemberInfo property = typeof(ABC).GetProperty(s); 
var dd = property.GetCustomAttribute(typeof(DisplayAttribute)) as DisplayAttribute;
if(dd != null)
{
var name = dd.Name;
}

Get class DisplayName attribute value

using your example I got it working doing this:

 var displayName = typeof(Opportunity)
.GetCustomAttributes(typeof(DisplayNameAttribute), true)
.FirstOrDefault() as DisplayNameAttribute;

if (displayName != null)
Console.WriteLine(displayName.DisplayName);

This outputted "Opportunity".

Or for the more generic way you seem to be doing it:

public static string GetDisplayName<T>()
{
var displayName = typeof(T)
.GetCustomAttributes(typeof(DisplayNameAttribute), true)
.FirstOrDefault() as DisplayNameAttribute;

if (displayName != null)
return displayName.DisplayName;

return "";
}

Usage:

string displayName = GetDisplayName<Opportunity>();

GetCustomAttributes() returns an object[], so you need to apply the specific cast first before accessing the required property values.

Get the all the values of DisplayName attributes

If you don't really care for the DisplayName attribute, but the effective display name that will be used (for instance by data binding), the easiest is to use TypeDescriptor.GetProperties method:

var info = TypeDescriptor.GetProperties(typeof(Class1))
.Cast<PropertyDescriptor>()
.ToDictionary(p => p.Name, p => p.DisplayName);

Get [DisplayName] attribute of a property in strongly-typed way

There are two ways to do this:

Models.Test test = new Models.Test();
string DisplayName = test.GetDisplayName(t => t.Name);

string DisplayName = Helpers.GetDisplayName<Models.Test>(t => t.Name);

The first one works by virtue of writing a generic extension method to any TModel (which is all types). This means it will be available on any object and not just your model. Not really recommended but nice because of it's concise syntax.

The second method requires you to pass in the Type of the model it is - which you're already doing but as a parameter instead. This method is required to define type via Generics because Func expects it.

Here are the methods for you to check out.

Static extension method to all objects

public static string GetDisplayName<TModel, TProperty>(this TModel model, Expression<Func<TModel, TProperty>> expression) {

Type type = typeof(TModel);

MemberExpression memberExpression = (MemberExpression)expression.Body;
string propertyName = ((memberExpression.Member is PropertyInfo) ? memberExpression.Member.Name : null);

// First look into attributes on a type and it's parents
DisplayAttribute attr;
attr = (DisplayAttribute)type.GetProperty(propertyName).GetCustomAttributes(typeof(DisplayAttribute), true).SingleOrDefault();

// Look for [MetadataType] attribute in type hierarchy
// http://stackoverflow.com/questions/1910532/attribute-isdefined-doesnt-see-attributes-applied-with-metadatatype-class
if (attr == null) {
MetadataTypeAttribute metadataType = (MetadataTypeAttribute)type.GetCustomAttributes(typeof(MetadataTypeAttribute), true).FirstOrDefault();
if (metadataType != null) {
var property = metadataType.MetadataClassType.GetProperty(propertyName);
if (property != null) {
attr = (DisplayAttribute)property.GetCustomAttributes(typeof(DisplayNameAttribute), true).SingleOrDefault();
}
}
}
return (attr != null) ? attr.Name : String.Empty;

}

Signature for type specific method - same code as above just different call

public static string GetDisplayName<TModel>(Expression<Func<TModel, object>> expression) { }

The reason you can't just use Something.GetDisplayName(t => t.Name) on it's own is because in the Razor engine you're actually passing an instantiated object of HtmlHelper<TModel> which is why the first method requires an instantiated object - This is only required for the compiler to infer what types belong to which generic name.

Update with recursive properties

public static string GetDisplayName<TModel>(Expression<Func<TModel, object>> expression) {

Type type = typeof(TModel);

string propertyName = null;
string[] properties = null;
IEnumerable<string> propertyList;
//unless it's a root property the expression NodeType will always be Convert
switch (expression.Body.NodeType) {
case ExpressionType.Convert:
case ExpressionType.ConvertChecked:
var ue = expression.Body as UnaryExpression;
propertyList = (ue != null ? ue.Operand : null).ToString().Split(".".ToCharArray()).Skip(1); //don't use the root property
break;
default:
propertyList = expression.Body.ToString().Split(".".ToCharArray()).Skip(1);
break;
}

//the propert name is what we're after
propertyName = propertyList.Last();
//list of properties - the last property name
properties = propertyList.Take(propertyList.Count() - 1).ToArray(); //grab all the parent properties

Expression expr = null;
foreach (string property in properties) {
PropertyInfo propertyInfo = type.GetProperty(property);
expr = Expression.Property(expr, type.GetProperty(property));
type = propertyInfo.PropertyType;
}

DisplayAttribute attr;
attr = (DisplayAttribute)type.GetProperty(propertyName).GetCustomAttributes(typeof(DisplayAttribute), true).SingleOrDefault();

// Look for [MetadataType] attribute in type hierarchy
// http://stackoverflow.com/questions/1910532/attribute-isdefined-doesnt-see-attributes-applied-with-metadatatype-class
if (attr == null) {
MetadataTypeAttribute metadataType = (MetadataTypeAttribute)type.GetCustomAttributes(typeof(MetadataTypeAttribute), true).FirstOrDefault();
if (metadataType != null) {
var property = metadataType.MetadataClassType.GetProperty(propertyName);
if (property != null) {
attr = (DisplayAttribute)property.GetCustomAttributes(typeof(DisplayNameAttribute), true).SingleOrDefault();
}
}
}
return (attr != null) ? attr.Name : String.Empty;

}

How to get the Display Name Attribute of an Enum member via MVC Razor code?

UPDATE

First solution was focused on getting display names from enum. Code below should be exact solution for your problem.

You can use this helper class for enums:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Reflection;

public static class EnumHelper<T>
where T : struct, Enum // This constraint requires C# 7.3 or later.
{
public static IList<T> GetValues(Enum value)
{
var enumValues = new List<T>();

foreach (FieldInfo fi in value.GetType().GetFields(BindingFlags.Static | BindingFlags.Public))
{
enumValues.Add((T)Enum.Parse(value.GetType(), fi.Name, false));
}
return enumValues;
}

public static T Parse(string value)
{
return (T)Enum.Parse(typeof(T), value, true);
}

public static IList<string> GetNames(Enum value)
{
return value.GetType().GetFields(BindingFlags.Static | BindingFlags.Public).Select(fi => fi.Name).ToList();
}

public static IList<string> GetDisplayValues(Enum value)
{
return GetNames(value).Select(obj => GetDisplayValue(Parse(obj))).ToList();
}

private static string lookupResource(Type resourceManagerProvider, string resourceKey)
{
var resourceKeyProperty = resourceManagerProvider.GetProperty(resourceKey,
BindingFlags.Static | BindingFlags.Public, null, typeof(string),
new Type[0], null);
if (resourceKeyProperty != null)
{
return (string)resourceKeyProperty.GetMethod.Invoke(null, null);
}

return resourceKey; // Fallback with the key name
}

public static string GetDisplayValue(T value)
{
var fieldInfo = value.GetType().GetField(value.ToString());

var descriptionAttributes = fieldInfo.GetCustomAttributes(
typeof(DisplayAttribute), false) as DisplayAttribute[];

if (descriptionAttributes[0].ResourceType != null)
return lookupResource(descriptionAttributes[0].ResourceType, descriptionAttributes[0].Name);

if (descriptionAttributes == null) return string.Empty;
return (descriptionAttributes.Length > 0) ? descriptionAttributes[0].Name : value.ToString();
}
}

And then you can use it in your view as following:

<ul>
@foreach (var value in @EnumHelper<UserPromotion>.GetValues(UserPromotion.None))
{
if (value == Model.JobSeeker.Promotion)
{
var description = EnumHelper<UserPromotion>.GetDisplayValue(value);
<li>@Html.DisplayFor(e => description )</li>
}
}
</ul>

Hope it helps! :)



Related Topics



Leave a reply



Submit