public class Class1
{
[DisplayName("Something To Name")]
public virtual string Name { get; set; }
}
C#でDisplayName属性の値を取得する方法は?
私のこれらのユーティリティメソッドを試してください:
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);
プロパティに関連付けられたPropertyInfo
を取得する必要があります(例:typeof(Class1).GetProperty("Name")
経由)。次に、 GetCustomAttributes
を呼び出します。
複数の値を返すため、少し面倒です-いくつかの場所から必要な場合は、これを行うヘルパーメソッドを作成することをお勧めします。 (フレームワークには既にどこかにヘルパーメソッドがあるかもしれませんが、もしあれば私はそれを知りません。)
編集:leppieが指摘したように、そこにisそのようなメソッド: Attribute.GetCustomAttribute(MemberInfo, Type)
最初に、そのプロパティを表すMemberInfo
オブジェクトを取得する必要があります。何らかの形の反射を行う必要があります。
MemberInfo property = typeof(Class1).GetProperty("Name");
(「古いスタイル」のリフレクションを使用していますが、コンパイル時に型にアクセスできる場合は式ツリーも使用できます)
次に、属性をフェッチして、DisplayName
プロパティの値を取得できます。
var attribute = property.GetCustomAttributes(typeof(DisplayNameAttribute), true)
.Cast<DisplayNameAttribute>().Single();
string displayName = attribute.DisplayName;
()括弧はタイプミスが必要です
Class1が強く型付けされたビューモデルであるビュー内から:
ModelMetadata.FromLambdaExpression<Class1, string>(x => x.Name, ViewData).DisplayName;
誰かが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();
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 = 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を作成し、必要なプロパティと表示名の属性のみを使用して装飾し、それらのリストを作成することを好みます。
お役に立てれば。
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(foo);
foreach (PropertyDescriptor property in properties)
{
if (property.Name == "Name")
{
Console.WriteLine(property.DisplayName); // Something To Name
}
}
ここで、foo
はClass1
のインスタンスです
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
の値を提供します。
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)));
}
テスト方法の出力:
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;
}
以下のコードを試してください、これはあなたの問題を解決すると思います。
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);
}