Lấy thuộc tính của giá trị Enum


483

Tôi muốn biết nếu có thể có được các thuộc tính của các enumgiá trị chứ không phải của enumchính nó? Ví dụ: giả sử tôi có những điều sau đây enum:

using System.ComponentModel; // for DescriptionAttribute

enum FunkyAttributesEnum
{
    [Description("Name With Spaces1")]
    NameWithoutSpaces1,    
    [Description("Name With Spaces2")]
    NameWithoutSpaces2
}

Những gì tôi muốn được đưa ra loại enum, tạo ra 2-tuples giá trị chuỗi enum và mô tả của nó.

Giá trị thật dễ dàng:

Array values = System.Enum.GetValues(typeof(FunkyAttributesEnum));
foreach (int value in values)
    Tuple.Value = Enum.GetName(typeof(FunkyAttributesEnum), value);

Nhưng làm thế nào để tôi có được giá trị của thuộc tính mô tả, để cư trú Tuple.Desc? Tôi có thể nghĩ làm thế nào để làm điều đó nếu Thuộc tính thuộc về enumchính nó, nhưng tôi không biết làm thế nào để có được nó từ giá trị của enum.


Từ một câu hỏi khác stackoverflow.com/questions/469287/
Mạnh


2
không gian tên cần thiết cho Mô tả là System.ComponentModel
John M

Bạn cũng có thể không sử dụng System.ComponentModel và chỉ sử dụng loại thuộc tính của riêng bạn; thực sự không có gì đặc biệt cả DescriptionAttribute.
jrh

Câu trả lời:


482

Điều này sẽ làm những gì bạn cần.

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;

10
Tùy chọn sử dụng type.GetFields (BindingFlags.Public | BindingFlags.Static) để nhận tất cả các memInfos cùng một lúc.
TrueWill

4
Tôi đã phải đi typeof (FunkyAttributEnum), nhưng khác hơn là nó hoạt động tốt. Cảm ơn.
Greg Randall

@AlexK Tôi không thấy lớp Enum có thuộc tính NameWithoutSpaces1. FunkyAttributEnum.NameWithoutSpaces1 đến từ đâu?
Don

2
@Don, đó là tên thành viên enum từ câu hỏi của OP.
MEMark

287

Đoạn mã này sẽ cung cấp cho bạn một phương thức mở rộng nhỏ xinh trên bất kỳ enum nào cho phép bạn truy xuất một thuộc tính chung. Tôi tin rằng nó khác với chức năng lambda ở trên vì nó đơn giản hơn để sử dụng và hơi đơn giản - bạn chỉ cần chuyển qua loại chung.

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><![CDATA[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;
    }
}

19
Cách sử dụng sau đó sẽ là: chuỗi desc = myEnumVariable.GetAttributionOfType <Mô tảAttribution> (). Mô tả;
Brad Rem

2
Tôi thích cái này hơn Scott, vì cách sử dụng ở đây sạch hơn (ít gõ hơn), vì vậy +1 :)
nawfal

3
Nếu không có thuộc tính tồn tại, điều này sẽ không ném IndexOutOfRangeException?
Erik Philips

6
sử dụng tốt hơn loại.GetMember (Enum.GetName (loại, enumVal)) cho memInfo là enumVal.ToString () có thể không đáng tin cậy cho các địa phương khác nhau.
Lin Song Yang

2
Điểm gọi GetCustomAttributes()sau đó lấy phần tử đầu tiên thay vì gọi là GetCustomAttribute()gì?
tigrou

81

Đây là một triển khai chung sử dụng lambda cho lựa chọn

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

Gọi nó như thế này:

string description = targetLevel.GetAttributeValue<DescriptionAttribute, string>(x => x.Description);

4
Điều đó thật tuyệt. Chúng ta chỉ cần cẩn thận nếu giá trị liệt kê đã cho là kết hợp (được cho phép FlagsAttribute). Trong trường hợp này, enumeration.GetType().GetMember(enumeration.ToString())[0]sẽ thất bại.
remio

Ngắn nhất bạn có thể viết : value.GetType().GetField(value.ToString()).GetCustomAttributes(false).OfType<T>‌​().SingleOrDefault(), nhưng phải thừa nhận cách rõ ràng của bạn là tốt hơn.
nawfal

2
Tôi cũng thêm chuỗi GetDes mô tả tĩnh công khai (bảng liệt kê Enum này) {return enumutions.GetAttributionValue <descriptionAttribution, String> (x => x.Descrip); } theo cách đó chỉ là targetLevel.GetDes mô tả ();
MarkKGreenway

65

Tôi đã hợp nhất một vài câu trả lời ở đây để tạo ra một giải pháp mở rộng hơn một chút. Tôi sẽ cung cấp nó trong trường hợp nó hữu ích cho bất kỳ ai khác trong tương lai. Đăng bài gốc tại đây .

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

}

Giải pháp này tạo ra một cặp phương thức mở rộng trên Enum. Cái đầu tiên cho phép bạn sử dụng sự phản chiếu để lấy bất kỳ thuộc tính nào được liên kết với giá trị của bạn. Cuộc gọi thứ hai đặc biệt lấy DescriptionAttributevà trả lạiDescription giá trị .

Ví dụ, xem xét sử dụng DescriptionAttributethuộc tính từ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
}

Để sử dụng phương thức mở rộng ở trên, bây giờ bạn chỉ cần gọi như sau:

Console.WriteLine(Days.Mon.ToName());

hoặc là

var day = Days.Mon;
Console.WriteLine(day.ToName());

Trên dòng cuối cùng, bạn có nghĩa là "thuộc tính. Mô tả"? Trả về thuộc tính == null? value.ToString (): property.Des mô tả;
Jeson Martajaya

2
Tôi thích giải pháp này, nhưng có một lỗi trong đó. Phương thức GetAttribution giả định rằng giá trị enum có thuộc tính Mô tả và do đó sẽ ném một ngoại lệ khi độ dài thuộc tính là 0. Thay thế các thuộc tính "return (T) [0];" với "return (thuộc tính. Độ dài> 0? (T) thuộc tính [0]: null);"
Simon Gymer

@SimonGymer cảm ơn vì lời đề nghị - Tôi đã cập nhật tương ứng. :)
Troy Alford

38

Ngoài phản hồi của AdamCrawford , tôi còn tạo thêm một phương thức mở rộng chuyên biệt hơn để cung cấp mô tả.

public static string GetAttributeDescription(this Enum enumValue)
{
    var attribute = enumValue.GetAttributeOfType<DescriptionAttribute>();
    return attribute == null ? String.Empty : attribute.Description;
} 

do đó, để có được mô tả, bạn có thể sử dụng phương thức mở rộng ban đầu như

string desc = myEnumVariable.GetAttributeOfType<DescriptionAttribute>().Description

hoặc bạn chỉ có thể gọi phương thức mở rộng ở đây là:

string desc = myEnumVariable.GetAttributeDescription();

Mà hy vọng sẽ làm cho mã của bạn dễ đọc hơn một chút.


16

Thông thạo một lớp lót ...

Ở đây tôi đang sử dụng DisplayAttributecái chứa cả thuộc tính NameDescription.

public static DisplayAttribute GetDisplayAttributesFrom(this Enum enumValue, Type enumType)
{
    return enumType.GetMember(enumValue.ToString())
                   .First()
                   .GetCustomAttribute<DisplayAttribute>();
}

Thí dụ

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

Đầu ra

Name: Sea cruise 
Description: Cruising on a dinghy

2
Tôi cũng sử dụng nó, đây là câu trả lời rõ ràng nhất! +1
Mafii

Điều này có vẻ khá hữu ích! Thnx
Irf

7

Đây là mã để lấy thông tin từ thuộc tính Display. Nó sử dụng một phương thức chung để lấy thuộc tính. Nếu không tìm thấy thuộc tính, nó chuyển đổi giá trị enum thành một chuỗi với trường hợp pascal / lạc đà được chuyển đổi sang trường hợp tiêu đề (mã thu được ở đây )

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

Và đây là phương thức mở rộng cho các chuỗi để chuyển đổi sang trường hợp tiêu đề:

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

4

Tôi đã triển khai phương thức mở rộng này để lấy mô tả từ các giá trị enum. Nó hoạt động cho tất cả các loại enum.

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

phiên bản chung của cùng một giải pháp đã được đăng. imo, tốt hơn
nawfal

4

Lấy từ điển từ enum.

public static IDictionary<string, int> ToDictionary(this Type enumType)
{
    return Enum.GetValues(enumType)
    .Cast<object>()
    .ToDictionary(v => ((Enum)v).ToEnumDescription(), k => (int)k); 
}

Bây giờ gọi nó như ...

var dic = typeof(ActivityType).ToDictionary();

Phương pháp mở rộng EnumDecription

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
}

3

Đây là phiên bản .NET Core của câu trả lời của AdamCrawford, sử dụng System.Reflection.TypeExtensions ;

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

Tôi không tin .NET Core (hay đúng hơn là Standard bây giờ) có GetMember nên tôi không chắc nó sẽ hoạt động như thế nào.
Jeff

Đó là trong System.Reflection.TypeExtensions, tôi đã sửa đổi câu trả lời của mình để liệt kê điều này.
wonea

1
Gotcha, cảm ơn. Tôi nghĩ rằng có thể có một số phần mở rộng tại chơi.
Jeff

3

Thêm giải pháp của tôi cho Net Framework và NetCore.

Tôi đã sử dụng điều này để thực hiện Net Framework của mình:

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

Điều này không hoạt động cho NetCore vì vậy tôi đã sửa đổi nó để làm điều này:

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

Ví dụ liệt kê:

public enum ExportTypes
{
    [Display( Name = "csv", Description = "text/csv" )]
    CSV = 0
}

Sử dụng mẫu cho thêm tĩnh:

var myDescription = myEnum.Description();

2

Tận dụng một số tính năng ngôn ngữ C # mới hơn, bạn có thể giảm số lượng dòng:

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

2

Tôi câu trả lời này để thiết lập một hộp tổ hợp từ một thuộc tính enum rất tuyệt.

Sau đó tôi cần mã hóa ngược lại để tôi có thể lấy vùng chọn từ hộp và trả lại enum theo đúng loại.

Tôi cũng đã sửa đổi mã để xử lý trường hợp thiếu thuộc tính

Vì lợi ích của người tiếp theo, đây là giải pháp cuối cùng của tôi

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

}


1
Người đàn ông tôi đã thấy rất nhiều giải pháp ngu ngốc và không giải thích được, và bạn đã giết nó. Cảm ơn bạn rất nhiều <3
Kadaj

2

Nếu enumgiá trị của bạn chứa một giá trị như Equalsbạn có thể gặp phải một vài lỗi sử dụng một số tiện ích mở rộng trong rất nhiều câu trả lời ở đây. Điều này là do thông thường được giả định rằng typeof(YourEnum).GetMember(YourEnum.Value)sẽ chỉ trả về một giá trị, đó là giá trị MemberInfocủa bạn enum. Đây là một phiên bản an toàn hơn một chút câu trả lời của 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
}

1

Phương thức mở rộng này sẽ có được biểu diễn chuỗi của một giá trị enum bằng XmlEnumAttribution của nó. Nếu không có XmlEnumAttribution, nó sẽ rơi trở lại 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;
}

1

Và nếu bạn muốn danh sách đầy đủ các tên, bạn có thể làm một cái gì đó như

typeof (PharmacyConfigurationKeys).GetFields()
        .Where(x => x.GetCustomAttributes(false).Any(y => typeof(DescriptionAttribute) == y.GetType()))
        .Select(x => ((DescriptionAttribute)x.GetCustomAttributes(false)[0]).Description);

0

Các bạn nếu nó giúp tôi sẽ chia sẻ với bạn giải pháp của tôi: Định nghĩa thuộc tính Tùy chỉnh:

    [AttributeUsage(AttributeTargets.Field,AllowMultiple = false)]
public class EnumDisplayName : Attribute
{
    public string Name { get; private set; }
    public EnumDisplayName(string name)
    {
        Name = name;
    }
}

Bây giờ bởi vì tôi cần nó bên trong HtmlHelper định nghĩa của HtmlHelper mở rộng:

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

Hy vọng nó giúp


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

Bây giờ nó sẽ tạo ra lỗi trong trường hợp này 1 "Equals"

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

vì vậy nếu nó là cùng một tên enum chứ không phải tên hiển thị vì enumMember.GetCustomAttribution () bị null nếu tên hiển thị và tên enum giống nhau .....


0

Ngoài ra, bạn có thể làm như sau:

List<SelectListItem> selectListItems = new List<SelectListItem>();

    foreach (var item in typeof(PaymentTerm).GetEnumValues())
    {
        var type = item.GetType();
        var name = type.GetField(item.ToString()).GetCustomAttributesData().FirstOrDefault()?.NamedArguments.FirstOrDefault().TypedValue.Value.ToString();
        selectListItems.Add(new SelectListItem(name, type.Name));

    }

0

Đây là cách tôi giải quyết nó mà không cần sử dụng trình trợ giúp hoặc tiện ích mở rộng tùy chỉnh với .NET core 3.1.

Lớp học

public enum YourEnum
{
    [Display(Name = "Suryoye means Arameans")]
    SURYOYE = 0,
    [Display(Name = "Oromoye means Syriacs")]
    OROMOYE = 1,
}

Dao cạo

@using Enumerations

foreach (var name in Html.GetEnumSelectList(typeof(YourEnum)))
{
    <h1>@name.Text</h1>
}

1
xem xét việc trả lời câu hỏi bằng cách sử dụng nhiều hơn cách bạn giải quyết 'nó' - bắt đầu bằng cách thừa nhận vấn đề và giải thích cách bạn nghĩ điều này giải quyết 'nó'. Hãy nhớ rằng câu trả lời của bạn có thể được đưa ra khỏi bối cảnh trong một số năm kể từ bây giờ và sau đó nó sẽ gần như vô dụng. Thêm nhiều hơn vào nó, thêm một số bối cảnh sẽ tăng cấp câu trả lời của bạn và mức độ phù hợp về lịch sử / lưu trữ của nó
OldFart

0

Vấn đề hiệu suất

Nếu bạn muốn hiệu suất tốt hơn đây là con đường để đi:

public static class AdvancedEnumExtensions
{
    /// <summary>
    /// Gets the custom attribute <typeparamref name="T"/> for the enum constant, if such a constant is defined and has such an attribute; otherwise null.
    /// </summary>
    public static T GetCustomAttribute<T>(this Enum value) where T : Attribute
    {
        return GetField(value)?.GetCustomAttribute<T>(inherit: false);
    }

    /// <summary>
    /// Gets the FieldInfo for the enum constant, if such a constant is defined; otherwise null.
    /// </summary>
    public static FieldInfo GetField(this Enum value)
    {
        ulong u64 = ToUInt64(value);
        return value
            .GetType()
            .GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static)
            .Where(f => ToUInt64(f.GetRawConstantValue()) == u64)
            .FirstOrDefault();
    }

    /// <summary>
    /// Checks if an enum constant is defined for this enum value
    /// </summary>
    public static bool IsDefined(this Enum value)
    {
        return GetField(value) != null;
    }

    /// <summary>
    /// Converts the enum value to UInt64
    /// </summary>
    public static ulong ToUInt64(this Enum value) => ToUInt64((object)value);

    private static ulong ToUInt64(object value)
    {
        switch (Convert.GetTypeCode(value))
        {
            case TypeCode.SByte:
            case TypeCode.Int16:
            case TypeCode.Int32:
            case TypeCode.Int64:
                return unchecked((ulong)Convert.ToInt64(value, CultureInfo.InvariantCulture));

            case TypeCode.Byte:
            case TypeCode.UInt16:
            case TypeCode.UInt32:
            case TypeCode.UInt64:
            case TypeCode.Char:
            case TypeCode.Boolean:
                return Convert.ToUInt64(value, CultureInfo.InvariantCulture);

            default: throw new InvalidOperationException("UnknownEnumType");
        }
    }
}

Tại sao điều này có hiệu suất tốt hơn?

Bởi vì tất cả các phương thức tích hợp đều sử dụng mã rất giống với điều này ngoại trừ chúng cũng chạy một loạt các mã khác mà chúng tôi không quan tâm . Mã Enum của C # nói chung khá kinh khủng.

Đoạn mã trên đã được Linq-ified và sắp xếp hợp lý để nó chỉ chứa các bit mà chúng ta quan tâm.

Tại sao mã tích hợp chậm?

Đầu tiên liên quan đến Enum.ToString () -vs- Enum.GetName (..)

Luôn luôn sử dụng cái sau. (Hoặc tốt hơn là không, như sẽ trở nên rõ ràng dưới đây.)

ToString () sử dụng cái sau trong nội bộ, nhưng một lần nữa, cũng thực hiện một loạt các thứ khác mà chúng tôi không muốn, ví dụ: cố gắng kết hợp cờ, in ra số, v.v. Chúng tôi chỉ quan tâm đến các hằng số được xác định bên trong enum.

Enum.GetName lần lượt lấy tất cả các trường, tạo một chuỗi chuỗi cho tất cả các tên, sử dụng ToUInt64 ở trên trên tất cả các RawConstantValues ​​của chúng để tạo một mảng UInt64 của tất cả các giá trị, sắp xếp cả hai mảng theo giá trị UInt64 và cuối cùng lấy tên từ mảng tên bằng cách thực hiện Tìm kiếm nhị phân trong mảng UInt64 để tìm chỉ mục của giá trị chúng tôi muốn.

... Và sau đó chúng ta ném các trường và các mảng được sắp xếp sử dụng tên đó để tìm lại trường.

Một từ: "Ư!"


-1

Ngoài ra, bạn có thể làm như sau:

Dictionary<FunkyAttributesEnum, string> description = new Dictionary<FunkyAttributesEnum, string>()
    {
      { FunkyAttributesEnum.NameWithoutSpaces1, "Name With Spaces1" },
      { FunkyAttributesEnum.NameWithoutSpaces2, "Name With Spaces2" },
    };

Và nhận được mô tả với những điều sau đây:

string s = description[FunkyAttributesEnum.NameWithoutSpaces1];

Theo tôi đây là một cách hiệu quả hơn để làm những gì bạn muốn thực hiện, vì không cần sự phản ánh ..


2
Chắc chắn, nhưng sự phản chiếu không tệ như mọi người nghĩ.
Bryan Rowe

Không nói rằng nó xấu - tôi sử dụng nó mọi lúc. Nó thường được sử dụng không cần thiết, mặc dù. :)
Ian P

44
Giải pháp này di chuyển mô tả ra khỏi enum, tạo ra ít nhất hai vấn đề lớn. Đầu tiên, nếu ai đó thêm hằng số enum mới, họ sẽ cần phải biết đi đến nơi khác để thêm mục vào đó. Các thuộc tính là một dấu hiệu rõ ràng cho một người duy trì những gì họ cần làm. Vấn đề thứ hai của tôi với nó là nó chỉ là nhiều mã hơn. Các thuộc tính là nhỏ gọn.
scobi

1
@scott nhưng nó cho phép bạn chỉ định đơn hàng của riêng mình và loại trừ các giá trị bạn không muốn hiển thị gần như luôn luôn là những gì tôi thực sự muốn
Simon_Weaver

-2

Bạn cũng có thể xác định một giá trị enum như Name_Without_Spaces, và khi bạn muốn có một sử dụng mô tả Name_Without_Spaces.ToString().Replace('_', ' ')để thay thế gạch với không gian.


8
Đây là một giải pháp rất không phù hợp. Cân nhắc sử dụng giải pháp được cung cấp bởi @Bryan
Johann
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.