私のモデルには "Promotion"という名前のプロパティがあり、その型は "UserPromotion"というフラグの列挙型です。私のenumのメンバーは次のように設定された表示属性を持っています:
[Flags]
public enum UserPromotion
{
None = 0x0,
[Display(Name = "Send Job Offers By Mail")]
SendJobOffersByMail = 0x1,
[Display(Name = "Send Job Offers By Sms")]
SendJobOffersBySms = 0x2,
[Display(Name = "Send Other Stuff By Sms")]
SendPromotionalBySms = 0x4,
[Display(Name = "Send Other Stuff By Mail")]
SendPromotionalByMail = 0x8
}
今、私は自分の "Promotion"プロパティの選択された値を表示するために私のビューでulと言うことができるようにしたいと思います。これは私がこれまで行ったことですが問題はどうすればここで表示名を取得できるかということです。
<ul>
@foreach (int aPromotion in @Enum.GetValues(typeof(UserPromotion)))
{
var currentPromotion = (int)Model.JobSeeker.Promotion;
if ((currentPromotion & aPromotion) == aPromotion)
{
<li>Here I don't know how to get the display attribute of "currentPromotion".</li>
}
}
</ul>
UPDATE
最初の解決策はenumから表示名を取得することに集中していました。以下のコードはあなたの問題に対する正確な解決策であるべきです。
このヘルパークラスを列挙型に使用できます。
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Reflection;
public static class EnumHelper<T>
{
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)
{
foreach (PropertyInfo staticProperty in resourceManagerProvider.GetProperties(BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public))
{
if (staticProperty.PropertyType == typeof(System.Resources.ResourceManager))
{
System.Resources.ResourceManager resourceManager = (System.Resources.ResourceManager)staticProperty.GetValue(null, null);
return resourceManager.GetString(resourceKey);
}
}
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();
}
}
そして、あなたは次のようにあなたの見解でそれを使用することができます:
<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>
それが役に立てば幸い! :)
ワンライナー - 流暢な構文
public static class Extensions
{
/// <summary>
/// A generic extension method that aids in reflecting
/// and retrieving any attribute that is applied to an `Enum`.
/// </summary>
public static TAttribute GetAttribute<TAttribute>(this Enum enumValue)
where TAttribute : Attribute
{
return enumValue.GetType()
.GetMember(enumValue.ToString())
.First()
.GetCustomAttribute<TAttribute>();
}
}
例
public enum Season
{
[Display(Name = "It's autumn")]
Autumn,
[Display(Name = "It's winter")]
Winter,
[Display(Name = "It's spring")]
Spring,
[Display(Name = "It's summer")]
Summer
}
public class Foo
{
public Season Season = Season.Summer;
public void DisplayName()
{
var seasonDisplayName = Season.GetAttribute<DisplayAttribute>();
Console.WriteLine("Which season is it?");
Console.WriteLine (seasonDisplayName.Name);
}
}
どの季節ですか?
夏です
Aydinのすばらしい答え を基にして、型パラメータを必要としない拡張メソッドを紹介します。
using System;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Reflection;
public static class EnumExtensions
{
public static string GetDisplayName(this Enum enumValue)
{
return enumValue.GetType()
.GetMember(enumValue.ToString())
.First()
.GetCustomAttribute<DisplayAttribute>()
.GetName();
}
}
注:Nameプロパティの代わりにGetName()を使用する必要があります。これにより、ResourceType属性プロパティを使用した場合にローカライズされた文字列が返されるようになります。
例
それを使うためには、あなたのビューの中でenum値を参照するだけです。
@{
UserPromotion promo = UserPromotion.SendJobOffersByMail;
}
Promotion: @promo.GetDisplayName()
出力
プロモーション:メールで求人を送る
Aydinの答えに基づいて (私たちはType
name__の値そのものからEnum
name__を簡単に得ることができるので、より「重複しない」実装をお勧めします。パラメータ????:
public static string GetDisplayName(this Enum enumValue)
{
return enumValue.GetType().GetMember(enumValue.ToString())
.First()
.GetCustomAttribute<DisplayAttribute>()
.Name;
}
編集(@Vahagn Nahapetyanのコメントに基づく)
public static string GetDisplayName(this Enum enumValue)
{
return enumValue.GetType()?
.GetMember(enumValue.ToString())?
.First()?
.GetCustomAttribute<DisplayAttribute>()?
.Name;
}
これで、とてもきれいに使えます。
public enum Season
{
[Display(Name = "The Autumn")]
Autumn,
[Display(Name = "The Weather")]
Winter,
[Display(Name = "The Tease")]
Spring,
[Display(Name = "The Dream")]
Summer
}
Season.Summer.GetDisplayName();
どれが
"夢"
MVC 5.1以上を使用している場合は、より単純で明確な方法があります。以下のように(System.ComponentModel.DataAnnotations
名前空間からの)データ注釈を使用するだけです。
public enum Color
{
[Display(Name = "Dark red")]
DarkRed,
[Display(Name = "Very dark red")]
VeryDarkRed,
[Display(Name = "Red or just black?")]
ReallyDarkRed
}
そしてビューでは、ちょうどそれを適切なhtmlヘルパーに入れるだけです:
@Html.EnumDropDownListFor(model => model.Color)
Type.GetMemberメソッド を使用してから、リフレクションを使用して 属性情報 を取得できます。
// display attribute of "currentPromotion"
var type = typeof(UserPromotion);
var memberInfo = type.GetMember(currentPromotion.ToString());
var attributes = memberInfo[0].GetCustomAttributes(typeof(DisplayAttribute), false);
var description = ((DisplayAttribute)attributes[0]).Name;
ここに同様の投稿がいくつかありました。
<ul>
@foreach (int aPromotion in @Enum.GetValues(typeof(UserPromotion)))
{
var currentPromotion = (int)Model.JobSeeker.Promotion;
if ((currentPromotion & aPromotion) == aPromotion)
{
<li>@Html.DisplayFor(e => currentPromotion)</li>
}
}
</ul>
Toddの素晴らしい答え の上に構築された Aydinの素晴らしい答え の上に、これがある。型パラメータを必要としない汎用拡張メソッド。
/// <summary>
/// Gets human-readable version of enum.
/// </summary>
/// <returns>DisplayAttribute.Name property of given enum.</returns>
public static string GetDisplayName<T>(this T enumValue) where T : IComparable, IFormattable, IConvertible
{
if (!typeof(T).IsEnum)
throw new ArgumentException("Argument must be of type Enum");
DisplayAttribute displayAttribute = enumValue.GetType()
.GetMember(enumValue.ToString())
.First()
.GetCustomAttribute<DisplayAttribute>();
string displayName = displayAttribute?.GetName();
return displayName ?? enumValue.ToString();
}
私のプロジェクトでこれが必要だったのは、enumのすべてのメンバーがDisplayAttribute
を持っているわけではない以下のコードのようなものがToddの解決策ではうまくいかないからです。
public class MyClass
{
public enum MyEnum
{
[Display(Name="ONE")]
One,
// No DisplayAttribute
Two
}
public void UseMyEnum()
{
MyEnum foo = MyEnum.One;
MyEnum bar = MyEnum.Two;
Console.WriteLine(foo.GetDisplayName());
Console.WriteLine(bar.GetDisplayName());
}
}
// Output:
//
// ONE
// Two
これが単純な問題に対する複雑な解決策である場合は、私に知らせてください。しかし、これが私が使用した修正でした。
その属性にアクセスするには、少しリフレクションを使用する必要があります。
var type = typeof(UserPromotion);
var member = type.GetMember(Model.JobSeeker.Promotion.ToString());
var attributes = member[0].GetCustomAttributes(typeof(DisplayAttribute), false);
var name = ((DisplayAttribute)attributes[0]).Name;
このメソッドを拡張メソッドでラップするか、ビューモデルで実行することをお勧めします。
Core 2.1では、
public static string GetDisplayName(Enum enumValue)
{
return enumValue.GetType()?
.GetMember(enumValue.ToString())?[0]?
.GetCustomAttribute<DisplayAttribute>()?
.Name;
}
AydinとToddの答えをさらに詳しく説明するために、リソースファイルから名前を取得するための拡張メソッドを次に示します。
using AppResources;
using System;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Reflection;
using System.Resources;
public static class EnumExtensions
{
public static string GetDisplayName(this Enum enumValue)
{
var enumMember= enumValue.GetType()
.GetMember(enumValue.ToString());
DisplayAttribute displayAttrib = null;
if (enumMember.Any()) {
displayAttrib = enumMember
.First()
.GetCustomAttribute<DisplayAttribute>();
}
string name = null;
Type resource = null;
if (displayAttrib != null)
{
name = displayAttrib.Name;
resource = displayAttrib.ResourceType;
}
return String.IsNullOrEmpty(name) ? enumValue.ToString()
: resource == null ? name
: new ResourceManager(resource).GetString(name);
}
}
そしてそれを好きに使う
public enum Season
{
[Display(ResourceType = typeof(Resource), Name = Season_Summer")]
Summer
}
申し訳ありませんが、他の回答をそのまま使用することはできず、コメントに載せる時間がありません。
C#6の構文を使用します。
static class EnumExtensions
{
/// returns the localized Name, if a [Display(Name="Localised Name")] attribute is applied to the enum member
/// returns null if there isnt an attribute
public static string DisplayNameOrEnumName(this Enum value)
// => value.DisplayNameOrDefault() ?? value.ToString()
{
// More efficient form of ^ based on http://stackoverflow.com/a/17034624/11635
var enumType = value.GetType();
var enumMemberName = Enum.GetName(enumType, value);
return enumType
.GetEnumMemberAttribute<DisplayAttribute>(enumMemberName)
?.GetName() // Potentially localized
?? enumMemberName; // Or fall back to the enum name
}
/// returns the localized Name, if a [Display] attribute is applied to the enum member
/// returns null if there is no attribute
public static string DisplayNameOrDefault(this Enum value) =>
value.GetEnumMemberAttribute<DisplayAttribute>()?.GetName();
static TAttribute GetEnumMemberAttribute<TAttribute>(this Enum value) where TAttribute : Attribute =>
value.GetType().GetEnumMemberAttribute<TAttribute>(value.ToString());
static TAttribute GetEnumMemberAttribute<TAttribute>(this Type enumType, string enumMemberName) where TAttribute : Attribute =>
enumType.GetMember(enumMemberName).Single().GetCustomAttribute<TAttribute>();
}
上からすべてのエッジケースを組み合わせます:
Equals
、ToString
)を持つenumメンバーDisplay
属性ここに私のコードがあります:
public enum Enum
{
[Display(Name = "What a weird name!")]
ToString,
Equals
}
public static class EnumHelpers
{
public static string GetDisplayName(this Enum enumValue)
{
var enumType = enumValue.GetType();
return enumType
.GetMember(enumValue.ToString())
.Where(x => x.MemberType == MemberTypes.Field && ((FieldInfo)x).FieldType == enumType)
.First()
.GetCustomAttribute<DisplayAttribute>()?.Name ?? enumValue.ToString();
}
}
void Main()
{
Assert.Equals("What a weird name!", Enum.ToString.GetDisplayName());
Assert.Equals("Equals", Enum.Equals.GetDisplayName());
}
以前の回答に基づいて、私は読みやすい方法ですべてのDisplayAttributeプロパティをサポートするためにこの快適なヘルパーを作成しました:
public static class EnumExtensions
{
public static DisplayAttributeValues GetDisplayAttributeValues(this Enum enumValue)
{
var displayAttribute = enumValue.GetType().GetMember(enumValue.ToString()).First().GetCustomAttribute<DisplayAttribute>();
return new DisplayAttributeValues(enumValue, displayAttribute);
}
public sealed class DisplayAttributeValues
{
private readonly Enum enumValue;
private readonly DisplayAttribute displayAttribute;
public DisplayAttributeValues(Enum enumValue, DisplayAttribute displayAttribute)
{
this.enumValue = enumValue;
this.displayAttribute = displayAttribute;
}
public bool? AutoGenerateField => this.displayAttribute?.GetAutoGenerateField();
public bool? AutoGenerateFilter => this.displayAttribute?.GetAutoGenerateFilter();
public int? Order => this.displayAttribute?.GetOrder();
public string Description => this.displayAttribute != null ? this.displayAttribute.GetDescription() : string.Empty;
public string GroupName => this.displayAttribute != null ? this.displayAttribute.GetGroupName() : string.Empty;
public string Name => this.displayAttribute != null ? this.displayAttribute.GetName() : this.enumValue.ToString();
public string Prompt => this.displayAttribute != null ? this.displayAttribute.GetPrompt() : string.Empty;
public string ShortName => this.displayAttribute != null ? this.displayAttribute.GetShortName() : this.enumValue.ToString();
}
}
MVC5を使用すると、使用することができます:
public enum UserPromotion
{
None = 0x0,
[Display(Name = "Send Job Offers By Mail")]
SendJobOffersByMail = 0x1,
[Display(Name = "Send Job Offers By Sms")]
SendJobOffersBySms = 0x2,
[Display(Name = "Send Other Stuff By Sms")]
SendPromotionalBySms = 0x4,
[Display(Name = "Send Other Stuff By Mail")]
SendPromotionalByMail = 0x8
}
あなたがドロップダウンセレクタを作成したい場合は、あなたが使用することができます:
@Html.EnumDropdownListFor(expression: model => model.PromotionSelector, optionLabel: "Select")
私は文化に依存するGetDisplayName列挙型拡張に貢献したいです。これが私のようにこの答えをグーグルする人にとって有用であることを願っています:
Aydin Adn および Todd のような「標準」の方法:
public static string GetDisplayName(this Enum enumValue)
{
return enumValue
.GetType()
.GetMember(enumValue.ToString())
.First()
.GetCustomAttribute<DisplayAttribute>()
.GetName();
}
「文化に依存する」方法:
public static string GetDisplayName(this Enum enumValue, CultureInfo ci)
{
var displayAttr = enumValue
.GetType()
.GetMember(enumValue.ToString())
.First()
.GetCustomAttribute<DisplayAttribute>();
var resMan = displayAttr.ResourceType?.GetProperty(@"ResourceManager", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).GetValue(null, null) as ResourceManager;
return resMan?.GetString(displayAttr.Name, ci) ?? displayAttr.GetName();
}
私はこれを編集としてやろうとしましたが拒絶されました。理由がわかりません。
カスタム属性と普通の項目が混在するEnumを使って呼び出すと、上記は例外をスローします。
public enum CommentType
{
All = 1,
Rent = 2,
Insurance = 3,
[Display(Name="Service Charge")]
ServiceCharge = 4
}
そのため、アクセスする前にカスタム属性をチェックし、見つからない場合は名前を使用するようにコードを少しだけ変更しました。
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Reflection;
public static class EnumHelper<T>
{
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)
{
foreach (PropertyInfo staticProperty in resourceManagerProvider.GetProperties(BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public))
{
if (staticProperty.PropertyType == typeof(System.Resources.ResourceManager))
{
System.Resources.ResourceManager resourceManager = (System.Resources.ResourceManager)staticProperty.GetValue(null, null);
return resourceManager.GetString(resourceKey);
}
}
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.Any() && 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();
}
}