c# सरक एनम के मूल्य के गुण प्राप्त करना




राजस्थान सरकार द्वारा ए. एन. एम. की भर्ती 2017-18 (16)

मैं जानना चाहूंगा कि enum मूल्यों के गुण प्राप्त करना संभव है, न कि enum के अपने आप? उदाहरण के लिए, मान लें कि मेरे पास निम्नलिखित enum है:

using System.ComponentModel; // for DescriptionAttribute

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

जो मैं चाहता हूं उसे enum प्रकार दिया जाता है, enum स्ट्रिंग मान के 2-tuples और इसके विवरण का उत्पादन।

मूल्य आसान था:

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

लेकिन Tuple.Desc को पॉप्युलेट करने के लिए, मैं विवरण विशेषता का मूल्य कैसे प्राप्त करूं? मैं यह सोच सकता हूं कि यह गुण कैसे किया जाए यदि विशेषता enum से संबंधित है, लेकिन मुझे नुकसान के कारण यह है कि इसे enum के मूल्य से कैसे प्राप्त किया जाए।


यह चयन के लिए लैम्ब्डा का उपयोग कर एक सामान्य कार्यान्वयन है

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

कोड के इस टुकड़े को आपको किसी भी enum पर एक अच्छा छोटा विस्तार विधि देना चाहिए जो आपको एक सामान्य विशेषता पुनर्प्राप्त करने देता है। मेरा मानना ​​है कि यह ऊपर लैम्ब्डा फ़ंक्शन से अलग है क्योंकि इसका उपयोग करना आसान है और थोड़ा - आपको केवल सामान्य प्रकार में गुजरना होगा।

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

Enum से शब्दकोश प्राप्त करें।

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
}

प्रदर्शन विशेषता से जानकारी प्राप्त करने के लिए कोड यहां दिया गया है। यह विशेषता पुनर्प्राप्त करने के लिए एक सामान्य विधि का उपयोग करता है। यदि विशेषता नहीं मिली है तो यह एनम मान को एक स्ट्रिंग में परिवर्तित करता है जिसमें पास्कल / ऊंट केस शीर्षक केस में परिवर्तित होता है ( 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 "));
    }

मैंने थोड़ा और विस्तार योग्य समाधान बनाने के लिए यहां कुछ जवाब विलय कर दिए हैं। मैं इसे भविष्य में किसी और के लिए उपयोगी होने पर ही प्रदान कर रहा हूं। 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;
    }

}

यह समाधान Enum पर एक्सटेंशन विधियों की एक जोड़ी बनाता है। सबसे पहले आपको अपने मूल्य से जुड़े किसी भी विशेषता को पुनर्प्राप्त करने के लिए प्रतिबिंब का उपयोग करने की अनुमति मिलती है। दूसरा विशेष कॉल DescriptionAttribute प्राप्त करता है और इसका Description मान देता है।

उदाहरण के तौर पर, System.ComponentModel से DescriptionAttribute विशेषता का उपयोग करने पर विचार करें

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

यह नेटकोर के लिए काम नहीं करता है इसलिए मैंने इसे करने के लिए इसे संशोधित किया:

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

और यदि आप नामों की पूरी सूची चाहते हैं तो आप कुछ ऐसा कर सकते हैं

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

    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 () डिस्प्लेनाम और एनम नाम समान हैं तो शून्य हो जाता है .....


दोस्तों अगर यह मदद करता है तो मैं आपके समाधान को आपके साथ साझा करूंगा: कस्टम विशेषता की परिभाषा:

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

अब क्योंकि मुझे HTMLHelper एक्सटेंशन की 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");
    }
}

आशा करता हूँ की ये काम करेगा


एक लाइनर सुस्त ...

यहां मैं 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

वैकल्पिक रूप से, आप निम्न कार्य कर सकते हैं:

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

और निम्नलिखित के साथ विवरण प्राप्त करें:

string s = description[FunkyAttributesEnum.NameWithoutSpaces1];

मेरी राय में यह पूरा करने का एक और अधिक प्रभावी तरीका है जिसे आप पूरा करना चाहते हैं, क्योंकि कोई प्रतिबिंब आवश्यक नहीं है ..


आप Name_Without_Spaces जैसे Name_Without_Spaces मान को भी परिभाषित कर सकते हैं, और जब आप विवरण का उपयोग करना चाहते हैं तो Name_Without_Spaces.ToString().Replace('_', ' ') स्पेस के साथ अंडरस्कोर को प्रतिस्थापित करने के लिए Name_Without_Spaces.ToString().Replace('_', ' ')


यह एक्सटेंशन विधि अपने 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;
}

मैं यह जवाब एक enum विशेषताओं से एक कॉम्बो बॉक्स स्थापित करने के लिए जो महान था।

इसके बाद मुझे रिवर्स को कोड करने की आवश्यकता थी ताकि मैं बॉक्स से चयन प्राप्त कर सकूं और एनम को सही प्रकार में वापस कर सकूं।

मैंने उस मामले को संभालने के लिए कोड को भी संशोधित किया जहां एक विशेषता गायब थी

अगले व्यक्ति के लाभों के लिए, मेरा अंतिम समाधान यहां है

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

}


मैंने enum मूल्यों से विवरण प्राप्त करने के लिए इस विस्तार विधि को कार्यान्वित किया। यह सभी तरह के enums के लिए काम करता है।

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

आपको जो चाहिए वह करना चाहिए।

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;




.net-attributes