Enum 값의 속성 얻기
열거 형 자체가 아닌 열거 형 값의 특성을 얻을 수 있는지 알고 싶습니다. 예를 들어 다음 열거 형이 있다고 가정합니다.
using System.ComponentModel; // for DescriptionAttribute
enum FunkyAttributesEnum
{
[Description("Name With Spaces1")]
NameWithoutSpaces1,
[Description("Name With Spaces2")]
NameWithoutSpaces2
}
내가 원하는 것은 열거 형 유형이 주어지고 2 튜플의 열거 형 문자열 값과 설명이 생성됩니다.
가치는 쉬웠다 :
Array values = System.Enum.GetValues(typeof(FunkyAttributesEnum));
foreach (int value in values)
Tuple.Value = Enum.GetName(typeof(FunkyAttributesEnum), value);
그러나 Tuple.Desc를 채우려면 설명 속성 값을 어떻게 얻습니까? 속성이 열거 형 자체에 속하면 어떻게 해야할지 생각할 수 있지만 열거 형 값에서 속성을 얻는 방법에 대해서는 손실이 있습니다.
필요한 작업을 수행해야합니다.
var enumType = typeof(FunkyAttributesEnum);
var memberInfos = enumType.GetMember(FunkyAttributesEnum.NameWithoutSpaces1.ToString());
var enumValueMemberInfo = memberInfos.FirstOrDefault(m => m.DeclaringType == enumType);
var valueAttributes =
enumValueMemberInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);
var description = ((DescriptionAttribute)valueAttributes[0]).Description;
이 코드는 일반 속성을 검색 할 수있는 열거 형에 멋진 확장 방법을 제공해야합니다. 나는 그것이 사용하기가 더 간단하고 약간이기 때문에 위의 람다 함수와 다르다고 생각합니다. 일반 유형 만 전달하면됩니다.
public static class EnumHelper
{
/// <summary>
/// Gets an attribute on an enum field value
/// </summary>
/// <typeparam name="T">The type of the attribute you want to retrieve</typeparam>
/// <param name="enumVal">The enum value</param>
/// <returns>The attribute of type T that exists on the enum value</returns>
/// <example>string desc = myEnumVariable.GetAttributeOfType<DescriptionAttribute>().Description;</example>
public static T GetAttributeOfType<T>(this Enum enumVal) where T:System.Attribute
{
var type = enumVal.GetType();
var memInfo = type.GetMember(enumVal.ToString());
var attributes = memInfo[0].GetCustomAttributes(typeof(T), false);
return (attributes.Length > 0) ? (T)attributes[0] : null;
}
}
이것은 선택을 위해 람다를 사용하는 일반적인 구현입니다.
public static Expected GetAttributeValue<T, Expected>(this Enum enumeration, Func<T, Expected> expression)
where T : Attribute
{
T attribute =
enumeration
.GetType()
.GetMember(enumeration.ToString())
.Where(member => member.MemberType == MemberTypes.Field)
.FirstOrDefault()
.GetCustomAttributes(typeof(T), false)
.Cast<T>()
.SingleOrDefault();
if (attribute == null)
return default(Expected);
return expression(attribute);
}
다음과 같이 호출하십시오.
string description = targetLevel.GetAttributeValue<DescriptionAttribute, string>(x => x.Description);
좀 더 확장 가능한 솔루션을 만들기 위해 여기에 몇 가지 답변을 병합했습니다. 앞으로 다른 사람에게 도움이 될 경우를 대비하여 제공하고 있습니다. 원래 게시물은 여기에 있습니다 .
using System;
using System.ComponentModel;
public static class EnumExtensions {
// This extension method is broken out so you can use a similar pattern with
// other MetaData elements in the future. This is your base method for each.
public static T GetAttribute<T>(this Enum value) where T : Attribute {
var type = value.GetType();
var memberInfo = type.GetMember(value.ToString());
var attributes = memberInfo[0].GetCustomAttributes(typeof(T), false);
return attributes.Length > 0
? (T)attributes[0]
: null;
}
// This method creates a specific call to the above method, requesting the
// Description MetaData attribute.
public static string ToName(this Enum value) {
var attribute = value.GetAttribute<DescriptionAttribute>();
return attribute == null ? value.ToString() : attribute.Description;
}
}
이 솔루션은 Enum에 확장 메소드 쌍을 만듭니다. 첫 번째는 리플렉션을 사용하여 값과 관련된 모든 속성을 검색 할 수 있습니다. 두 번째는 구체적으로 호출을 검색하여 값을 DescriptionAttribute
반환합니다 Description
.
예를 들어 DescriptionAttribute
속성을System.ComponentModel
using System.ComponentModel;
public enum Days {
[Description("Sunday")]
Sun,
[Description("Monday")]
Mon,
[Description("Tuesday")]
Tue,
[Description("Wednesday")]
Wed,
[Description("Thursday")]
Thu,
[Description("Friday")]
Fri,
[Description("Saturday")]
Sat
}
위의 확장 방법을 사용하려면 다음을 호출하면됩니다.
Console.WriteLine(Days.Mon.ToName());
또는
var day = Days.Mon;
Console.WriteLine(day.ToName());
AdamCrawford response 외에도 설명을 얻기 위해 피드를 제공하는보다 특수한 확장 메서드를 만들었습니다.
public static string GetAttributeDescription(this Enum enumValue)
{
var attribute = enumValue.GetAttributeOfType<DescriptionAttribute>();
return attribute == null ? String.Empty : attribute.Description;
}
따라서 설명을 얻으려면 원래 확장 방법을 다음과 같이 사용할 수 있습니다.
string desc = myEnumVariable.GetAttributeOfType<DescriptionAttribute>().Description
또는 단순히 다음과 같이 확장 메소드를 호출 할 수 있습니다.
string desc = myEnumVariable.GetAttributeDescription();
희망적으로 코드를 좀 더 읽기 쉽게 만들어야합니다.
유창한 라이너 ...
여기서는 및 속성 DisplayAttribute
이 모두 포함 된를 사용 Name
하고 Description
있습니다.
public static DisplayAttribute GetDisplayAttributesFrom(this Enum enumValue, Type enumType)
{
return enumType.GetMember(enumValue.ToString())
.First()
.GetCustomAttribute<DisplayAttribute>();
}
예
public enum ModesOfTransport
{
[Display(Name = "Driving", Description = "Driving a car")] Land,
[Display(Name = "Flying", Description = "Flying on a plane")] Air,
[Display(Name = "Sea cruise", Description = "Cruising on a dinghy")] Sea
}
void Main()
{
ModesOfTransport TransportMode = ModesOfTransport.Sea;
DisplayAttribute metadata = TransportMode.GetDisplayAttributesFrom(typeof(ModesOfTransport));
Console.WriteLine("Name: {0} \nDescription: {1}", metadata.Name, metadata.Description);
}
산출
Name: Sea cruise
Description: Cruising on a dinghy
다음은 Display 속성에서 정보를 얻는 코드입니다. 일반 메소드를 사용하여 속성을 검색합니다. 속성을 찾지 못하면 열거 형 값을 pascal / camel case를 title case로 변환 한 문자열로 변환합니다 (코드는 여기에서 획득 )
public static class EnumHelper
{
// Get the Name value of the Display attribute if the
// enum has one, otherwise use the value converted to title case.
public static string GetDisplayName<TEnum>(this TEnum value)
where TEnum : struct, IConvertible
{
var attr = value.GetAttributeOfType<TEnum, DisplayAttribute>();
return attr == null ? value.ToString().ToSpacedTitleCase() : attr.Name;
}
// Get the ShortName value of the Display attribute if the
// enum has one, otherwise use the value converted to title case.
public static string GetDisplayShortName<TEnum>(this TEnum value)
where TEnum : struct, IConvertible
{
var attr = value.GetAttributeOfType<TEnum, DisplayAttribute>();
return attr == null ? value.ToString().ToSpacedTitleCase() : attr.ShortName;
}
/// <summary>
/// Gets an attribute on an enum field value
/// </summary>
/// <typeparam name="TEnum">The enum type</typeparam>
/// <typeparam name="T">The type of the attribute you want to retrieve</typeparam>
/// <param name="value">The enum value</param>
/// <returns>The attribute of type T that exists on the enum value</returns>
private static T GetAttributeOfType<TEnum, T>(this TEnum value)
where TEnum : struct, IConvertible
where T : Attribute
{
return value.GetType()
.GetMember(value.ToString())
.First()
.GetCustomAttributes(false)
.OfType<T>()
.LastOrDefault();
}
}
제목 케이스로 변환하기위한 문자열의 확장 방법입니다.
/// <summary>
/// Converts camel case or pascal case to separate words with title case
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
public static string ToSpacedTitleCase(this string s)
{
//https://stackoverflow.com/a/155486/150342
CultureInfo cultureInfo = Thread.CurrentThread.CurrentCulture;
TextInfo textInfo = cultureInfo.TextInfo;
return textInfo
.ToTitleCase(Regex.Replace(s,
"([a-z](?=[A-Z0-9])|[A-Z](?=[A-Z][a-z]))", "$1 "));
}
열거 형에서 사전을 가져옵니다.
public static IDictionary<string, int> ToDictionary(this Type enumType)
{
return Enum.GetValues(enumType)
.Cast<object>()
.ToDictionary(v => ((Enum)v).ToEnumDescription(), k => (int)k);
}
이제 이렇게 불러
var dic = typeof(ActivityType).ToDictionary();
EnumDecription Ext 방법
public static string ToEnumDescription(this Enum en) //ext method
{
Type type = en.GetType();
MemberInfo[] memInfo = type.GetMember(en.ToString());
if (memInfo != null && memInfo.Length > 0)
{
object[] attrs = memInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
if (attrs != null && attrs.Length > 0)
return ((DescriptionAttribute)attrs[0]).Description;
}
return en.ToString();
}
public enum ActivityType
{
[Description("Drip Plan Email")]
DripPlanEmail = 1,
[Description("Modification")]
Modification = 2,
[Description("View")]
View = 3,
[Description("E-Alert Sent")]
EAlertSent = 4,
[Description("E-Alert View")]
EAlertView = 5
}
열거 형 값에서 설명을 얻기 위해이 확장 방법을 구현했습니다. 모든 종류의 열거 형에서 작동합니다.
public static class EnumExtension
{
public static string ToDescription(this System.Enum value)
{
FieldInfo fi = value.GetType().GetField(value.ToString());
var attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
return attributes.Length > 0 ? attributes[0].Description : value.ToString();
}
}
다음은 System.Reflection.TypeExtensions를 사용하여 AdamCrawford의 대답의 .NET Core 버전입니다 .
public static class EnumHelper
{
/// <summary>
/// Gets an attribute on an enum field value
/// </summary>
/// <typeparam name="T">The type of the attribute you want to retrieve</typeparam>
/// <param name="enumVal">The enum value</param>
/// <returns>The attribute of type T that exists on the enum value</returns>
/// <example>string desc = myEnumVariable.GetAttributeOfType<DescriptionAttribute>().Description;</example>
public static T GetAttributeOfType<T>(this Enum enumVal) where T : System.Attribute
{
var type = enumVal.GetType();
var memInfo = type.GetMember(enumVal.ToString());
IEnumerable<Attribute> attributes = memInfo[0].GetCustomAttributes(typeof(T), false);
return (T)attributes?.ToArray()[0];
}
}
Net Framework 및 NetCore에 대한 솔루션 추가
Net Framework 구현에 이것을 사용했습니다.
public static class EnumerationExtension
{
public static string Description( this Enum value )
{
// get attributes
var field = value.GetType().GetField( value.ToString() );
var attributes = field.GetCustomAttributes( typeof( DescriptionAttribute ), false );
// return description
return attributes.Any() ? ( (DescriptionAttribute)attributes.ElementAt( 0 ) ).Description : "Description Not Found";
}
}
NetCore에서는 작동하지 않으므로 다음과 같이 수정했습니다.
public static class EnumerationExtension
{
public static string Description( this Enum value )
{
// get attributes
var field = value.GetType().GetField( value.ToString() );
var attributes = field.GetCustomAttributes( false );
// Description is in a hidden Attribute class called DisplayAttribute
// Not to be confused with DisplayNameAttribute
dynamic displayAttribute = null;
if (attributes.Any())
{
displayAttribute = attributes.ElementAt( 0 );
}
// return description
return displayAttribute?.Description ?? "Description Not Found";
}
}
열거 형 예 :
public enum ExportTypes
{
[Display( Name = "csv", Description = "text/csv" )]
CSV = 0
}
정적 추가에 대한 샘플 사용법 :
var myDescription = myEnum.Description();
새로운 C # 언어 기능 중 일부를 활용하면 줄 수를 줄일 수 있습니다.
public static TAttribute GetEnumAttribute<TAttribute>(this Enum enumVal) where TAttribute : Attribute
{
var memberInfo = enumVal.GetType().GetMember(enumVal.ToString());
return memberInfo[0].GetCustomAttributes(typeof(TAttribute), false).OfType<TAttribute>().FirstOrDefault();
}
public static string GetEnumDescription(this Enum enumValue) => enumValue.GetEnumAttribute<DescriptionAttribute>()?.Description ?? enumValue.ToString();
이 답변은 열거 형 속성에서 콤보 상자를 설정하는 데 도움이되었습니다.
그런 다음 상자에서 선택 항목을 가져 와서 올바른 유형의 열거 형을 반환 할 수 있도록 역 코드를 작성해야했습니다.
또한 속성이 누락 된 경우를 처리하기 위해 코드를 수정했습니다.
다음 사람의 이익을 위해 여기에 나의 마지막 해결책이 있습니다.
public static class Program
{
static void Main(string[] args)
{
// display the description attribute from the enum
foreach (Colour type in (Colour[])Enum.GetValues(typeof(Colour)))
{
Console.WriteLine(EnumExtensions.ToName(type));
}
// Get the array from the description
string xStr = "Yellow";
Colour thisColour = EnumExtensions.FromName<Colour>(xStr);
Console.ReadLine();
}
public enum Colour
{
[Description("Colour Red")]
Red = 0,
[Description("Colour Green")]
Green = 1,
[Description("Colour Blue")]
Blue = 2,
Yellow = 3
}
}
public static class EnumExtensions
{
// This extension method is broken out so you can use a similar pattern with
// other MetaData elements in the future. This is your base method for each.
public static T GetAttribute<T>(this Enum value) where T : Attribute
{
var type = value.GetType();
var memberInfo = type.GetMember(value.ToString());
var attributes = memberInfo[0].GetCustomAttributes(typeof(T), false);
// check if no attributes have been specified.
if (((Array)attributes).Length > 0)
{
return (T)attributes[0];
}
else
{
return null;
}
}
// This method creates a specific call to the above method, requesting the
// Description MetaData attribute.
public static string ToName(this Enum value)
{
var attribute = value.GetAttribute<DescriptionAttribute>();
return attribute == null ? value.ToString() : attribute.Description;
}
/// <summary>
/// Find the enum from the description attribute.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="desc"></param>
/// <returns></returns>
public static T FromName<T>(this string desc) where T : struct
{
string attr;
Boolean found = false;
T result = (T)Enum.GetValues(typeof(T)).GetValue(0);
foreach (object enumVal in Enum.GetValues(typeof(T)))
{
attr = ((Enum)enumVal).ToName();
if (attr == desc)
{
result = (T)enumVal;
found = true;
break;
}
}
if (!found)
{
throw new Exception();
}
return result;
}
}
}
이 확장 메서드는 XmlEnumAttribute를 사용하여 열거 형 값의 문자열 표현을 가져옵니다. XmlEnumAttribute가 없으면 enum.ToString ()으로 폴백합니다.
public static string ToStringUsingXmlEnumAttribute<T>(this T enumValue)
where T: struct, IConvertible
{
if (!typeof(T).IsEnum)
{
throw new ArgumentException("T must be an enumerated type");
}
string name;
var type = typeof(T);
var memInfo = type.GetMember(enumValue.ToString());
if (memInfo.Length == 1)
{
var attributes = memInfo[0].GetCustomAttributes(typeof(System.Xml.Serialization.XmlEnumAttribute), false);
if (attributes.Length == 1)
{
name = ((System.Xml.Serialization.XmlEnumAttribute)attributes[0]).Name;
}
else
{
name = enumValue.ToString();
}
}
else
{
name = enumValue.ToString();
}
return name;
}
그리고 전체 이름 목록을 원하면 다음과 같이 할 수 있습니다.
typeof (PharmacyConfigurationKeys).GetFields()
.Where(x => x.GetCustomAttributes(false).Any(y => typeof(DescriptionAttribute) == y.GetType()))
.Select(x => ((DescriptionAttribute)x.GetCustomAttributes(false)[0]).Description);
enum
값이 포함되어 있으면 Equals
여기에 많은 답변으로 일부 확장을 사용하여 몇 가지 버그가 발생할 수 있습니다. 이것은 정상적으로 가정 때문이다 typeof(YourEnum).GetMember(YourEnum.Value)
는 IS 하나의 값을 반환 MemberInfo
하여의를 enum
. 다음은 Adam Crawford의 답변 보다 약간 더 안전한 버전 입니다.
public static class AttributeExtensions
{
#region Methods
public static T GetAttribute<T>(this Enum enumValue) where T : Attribute
{
var type = enumValue.GetType();
var memberInfo = type.GetMember(enumValue.ToString());
var member = memberInfo.FirstOrDefault(m => m.DeclaringType == type);
var attribute = Attribute.GetCustomAttribute(member, typeof(T), false);
return attribute is T ? (T)attribute : null;
}
#endregion
}
도움이된다면 내 솔루션을 공유 할 것입니다 : 사용자 정의 속성 정의 :
[AttributeUsage(AttributeTargets.Field,AllowMultiple = false)]
public class EnumDisplayName : Attribute
{
public string Name { get; private set; }
public EnumDisplayName(string name)
{
Name = name;
}
}
이제 HtmlHelper Extension의 HtmlHelper 정의 안에 필요했기 때문에 :
public static class EnumHelper
{
public static string EnumDisplayName(this HtmlHelper helper,EPriceType priceType)
{
//Get every fields from enum
var fields = priceType.GetType().GetFields();
//Foreach field skipping 1`st fieldw which keeps currently sellected value
for (int i = 0; i < fields.Length;i++ )
{
//find field with same int value
if ((int)fields[i].GetValue(priceType) == (int)priceType)
{
//get attributes of found field
var attributes = fields[i].GetCustomAttributes(false);
if (attributes.Length > 0)
{
//return name of found attribute
var retAttr = (EnumDisplayName)attributes[0];
return retAttr.Name;
}
}
}
//throw Error if not found
throw new Exception("Błąd podczas ustalania atrybutów dla typu ceny allegro");
}
}
그것이 도움이되기를 바랍니다.
public enum DataFilters
{
[Display(Name= "Equals")]
Equals = 1,// Display Name and Enum Name are same
[Display(Name= "Does Not Equal")]
DoesNotEqual = 2, // Display Name and Enum Name are different
}
이제이 경우 오류가 발생합니다. 1 "같음"
public static string GetDisplayName(this Enum enumValue)
{
var enumMember = enumValue.GetType().GetMember(enumValue.ToString()).First();
return enumMember.GetCustomAttribute<DisplayAttribute>() != null ? enumMember.GetCustomAttribute<DisplayAttribute>().Name : enumMember.Name;
}
따라서 표시 이름과 열거 이름이 동일한 경우 enumMember.GetCustomAttribute ()가 null을 반환하므로 표시 이름이 아닌 반환 열거 이름이 동일한 경우 .....
또는 다음을 수행 할 수 있습니다.
Dictionary<FunkyAttributesEnum, string> description = new Dictionary<FunkyAttributesEnum, string>()
{
{ FunkyAttributesEnum.NameWithoutSpaces1, "Name With Spaces1" },
{ FunkyAttributesEnum.NameWithoutSpaces2, "Name With Spaces2" },
};
그리고 다음과 같이 설명을 얻으십시오.
string s = description[FunkyAttributesEnum.NameWithoutSpaces1];
내 생각에 이것은 성찰이 필요하지 않기 때문에 당신이 성취하고자하는 것을하는보다 효율적인 방법입니다.
또한 enum 값을 정의 할 수 있으며 Name_Without_Spaces
, 설명을 원할 때 Name_Without_Spaces.ToString().Replace('_', ' ')
밑줄을 공백으로 바꾸는 데 사용할 수 있습니다.
참고 URL : https://stackoverflow.com/questions/1799370/getting-attributes-of-enums-value
'Programing' 카테고리의 다른 글
컨텐츠 스크립트를 사용하여 페이지 컨텍스트에 코드 삽입 (0) | 2020.02.17 |
---|---|
파이썬 모듈 소스의 위치는 어떻게 찾습니까? (0) | 2020.02.17 |
PHP + curl, HTTP POST 샘플 코드? (0) | 2020.02.17 |
UTF-8, UTF-16 및 UTF-32 (0) | 2020.02.16 |
jQuery 연기 및 약속-.then () vs .done () (0) | 2020.02.16 |