web-dev-qa-db-ja.com

DisplayName属性の値を取得します

public class Class1
{
    [DisplayName("Something To Name")]
    public virtual string Name { get; set; }
}

C#でDisplayName属性の値を取得する方法は?

61
user550937

私のこれらのユーティリティメソッドを試してください:

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);
74
Rich Tebb

プロパティに関連付けられたPropertyInfoを取得する必要があります(例:typeof(Class1).GetProperty("Name")経由)。次に、 GetCustomAttributes を呼び出します。

複数の値を返すため、少し面倒です-いくつかの場所から必要な場合は、これを行うヘルパーメソッドを作成することをお勧めします。 (フレームワークには既にどこかにヘルパーメソッドがあるかもしれませんが、もしあれば私はそれを知りません。)

編集:leppieが指摘したように、そこにisそのようなメソッド: Attribute.GetCustomAttribute(MemberInfo, Type)

29
Jon Skeet

最初に、そのプロパティを表すMemberInfoオブジェクトを取得する必要があります。何らかの形の反射を行う必要があります。

MemberInfo property = typeof(Class1).GetProperty("Name");

(「古いスタイル」のリフレクションを使用していますが、コンパイル時に型にアクセスできる場合は式ツリーも使用できます)

次に、属性をフェッチして、DisplayNameプロパティの値を取得できます。

var attribute = property.GetCustomAttributes(typeof(DisplayNameAttribute), true)
      .Cast<DisplayNameAttribute>().Single();
string displayName = attribute.DisplayName;

()括弧はタイプミスが必要です

27

Class1が強く型付けされたビューモデルであるビュー内から:

ModelMetadata.FromLambdaExpression<Class1, string>(x => x.Name, ViewData).DisplayName;
12
Luke Bennett

誰かがDisplayAttributeResourceTypeでプロパティからローカライズされた文字列を取得することに興味がある場合:

[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();
12
Matija Grcic

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;
            }
        }
    }
6
alex
var propInfo = new Class1().GetType().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を作成し、必要なプロパティと表示名の属性のみを使用して装飾し、それらのリストを作成することを好みます。

お役に立てれば。

4
Francis Rodgers
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(foo);

foreach (PropertyDescriptor property in properties)
{
    if (property.Name == "Name")
    {
        Console.WriteLine(property.DisplayName); // Something To Name
    }
}

ここで、fooClass1のインスタンスです

3
Foo

property型としてPropertyInfoを想定すると、これを1行で実行できます。

property.GetCustomAttributes(typeof(DisplayNameAttribute), true).Cast<DisplayNameAttribute>().Single().DisplayName

このコードを試してください:

EnumEntity.item.GetType().GetFields()[(int)EnumEntity.item].CustomAttributes.ToArray()[0].NamedArguments[0].TypedValue.ToString()

データ属性Nameの値を提供します。

1
Rafael

Rich TebbとMatt Bakerの回答に従って、LINQクエリでReflectionExtensionsメソッドを使用したかったのですが、機能しなかったため、このメソッドが機能するようにしました。

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

テスト方法の出力:

Test method output

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;

}

0
Xavave

以下のコードを試してください、これはあなたの問題を解決すると思います。

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);
}
0
Sid