c# - الحصول على سمات قيمة التعداد




reflection enums (13)

أود أن أعرف ما إذا كان من الممكن الحصول على سمات التعداد وليس التعداد نفسه؟ على سبيل المثال ، افترض أن لدي التعداد التالي:

using System.ComponentModel; // for DescriptionAttribute

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

ما أعطي هو إعطاء نوع التعداد ، وإنتاج 2-tuples من قيمة سلسلة التعداد ووصفه.

كانت القيمة سهلة:

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

ولكن كيف يمكنني الحصول على قيمة السمة الوصف ، لنشر Tuple.Desc؟ أستطيع أن أفكر في كيفية القيام بذلك إذا كانت السمة تنتمي إلى التعداد نفسه ، ولكن أنا في حيرة حول كيفية الحصول عليه من قيمة التعداد.


أنا هذا الجواب لإعداد مربع التحرير والسرد من سمات التعداد الذي كان كبيرا.

ثم أحتاج إلى رمز عكس ذلك حتى أتمكن من الحصول على التحديد من المربع وإرجاع التعداد في النوع الصحيح.

قمت أيضًا بتعديل الشفرة للتعامل مع الحالة التي كانت فيها إحدى السمات مفقودة

لفوائد الشخص التالي ، وهنا هو الحل النهائي

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

}


إذا كان ذلك يساعدني في مشاركتي معك الحل الخاص بي: تعريف السمة المخصصة:

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

الآن لأنني في حاجة إليها داخل HtmlHelper تعريف HtmlHelper Extension:

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

آمل أن يساعد


إليك رمز للحصول على معلومات من سمة العرض. ويستخدم طريقة عامة لاستعادة السمة. إذا لم يتم العثور على السمة فإنه يقوم بتحويل قيمة التعداد إلى سلسلة مع تحويل حالة pascal / camel إلى حالة العنوان (رمز تم الحصول عليه here )

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://.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 طريقة التحويلة

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

والتي من المفترض أن تجعل كودك أكثر قابلية للقراءة.


بدلاً من ذلك ، يمكنك القيام بما يلي:

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

واحصل على الوصف بما يلي:

string s = description[FunkyAttributesEnum.NameWithoutSpaces1];

في رأيي هذه طريقة أكثر فاعلية للقيام بما تريد تحقيقه ، حيث لا حاجة للتفكير.


قمت بتطبيق طريقة التمديد هذه للحصول على الوصف من قيم التعداد. إنه يعمل لكل أنواع التعدادات.

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

لقد دمجت اثنين من الإجابات هنا لإنشاء حل قابل للتوسيع أكثر قليلاً. أنا أقدم ذلك فقط في حالة أنه من المفيد لأي شخص آخر في المستقبل. النشر الأصلي here .

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 (T)attributes[0];
    }

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

}

ينشئ هذا الحل زوج من أساليب ملحق على التعداد. يسمح لك الأول باستخدام الانعكاس لاسترداد أي سمة مرتبطة بقيمتك. تقوم المكالمة الثانية بالتحديد باسترجاع 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());

هذا هو تطبيق عام باستخدام لامدا للتحديد

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

هذا يجب أن يفعل ما تحتاجه.

var type = typeof(FunkyAttributesEnum);
var memInfo = type.GetMember(FunkyAttributesEnum.NameWithoutSpaces1.ToString());
var attributes = memInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
var description = ((DescriptionAttribute)attributes[0]).Description;

يجب أن تمنحك هذه الشفرة طريقة ملحق صغيرة لطيفة على أي تعداد يسمح لك باسترداد سمة عامة. أعتقد أنه مختلف عن وظيفة lambda أعلاه لأنه أسهل في الاستخدام وقليلاً - تحتاج فقط إلى المرور بنوع عام.

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

يمكنك أيضًا تحديد قيمة التعداد مثل Name_Without_Spaces ، وعندما تريد استخدام الوصف Name_Without_Spaces.ToString().Replace('_', ' ') لاستبدال Name_Without_Spaces.ToString().Replace('_', ' ') السفلية بمسافات.


    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 إذا كان اسم العرض واسم enum نفس .....





.net-attributes