6

だから私は私のから取得する必要がありList<string>ますenum

これが私がこれまでに行ったことです:

列挙定義

    [Flags]
    public enum ContractorType
    {
        [Description("Recipient")]
        RECIPIENT = 1,
        [Description("Deliver")]
        DELIVER = 2,
        [Description("Recipient / Deliver")]
        RECIPIENT_DELIVER = 4
    }

必要なことを行うためのメソッドを持つ HelperClass:

public static class EnumUtils
{
    public static IEnumerable<string> GetDescrptions(Type enumerator)
    {
        FieldInfo[] fi = enumerator.GetFields();

        List<DescriptionAttribute> attributes = new List<DescriptionAttribute>();
        foreach (var i in fi)
        {
            try
            {
                yield return attributes.Add(((DescriptionAttribute[])i.GetCustomAttributes(
                    typeof(DescriptionAttribute),
                    false))[0]);
            }
            catch { }
        }
        return new List<string>{"empty"};
    }
}

今、yield私が大切にしている行で、NullReferenceException. 私は何か見落としてますか?構文は私には問題ないように見えますが、何か見落としているのでしょうか?

編集: ここでは .net Framework 4.0 を使用しています。

4

7 に答える 7

4

ここに小さな再利用可能なソリューションがあります。これは、型Tから型Kのすべての属性を抽出する抽象クラスです。

abstract class AbstractAttributes<T, K>
{
    protected List<K> Attributes = new List<K>();

    public AbstractAttributes()
    {
        foreach (var member in typeof(T).GetMembers())
        {
            foreach (K attribute in member.GetCustomAttributes(typeof(K), true)) 
                Attributes.Add(attribute);                
        }
    }
}

タイプの属性のみを抽出する必要DescriptionAttributeがある場合は、次のクラスを使用します。

class DescriptionAttributes<T> : AbstractAttributes<T, DescriptionAttribute>
{
    public List<string> Descriptions { get; set; }

    public DescriptionAttributes()
    {
        Descriptions = Attributes.Select(x => x.Description).ToList();
    }
}

DescriptionAttributeこのクラスは、 type から type の属性のみを抽出しますT。しかし、実際にこのクラスをコンテキストで使用するには、次のことを行うだけです。

new DescriptionAttributes<ContractorType>().Descriptions.ForEach(x => Console.WriteLine(x));

このコード行は、 type の属性でパラメーターとして使用したすべての説明を書き出しますDescriptionAttribute。他の属性を抽出する必要がある場合は、クラスから派生する新しいクラスを作成し、AbstractAttributes<T, K>その型Kを適切な属性で閉じます。

于 2013-06-02T20:59:27.363 に答える
2

存在する場合は、各フィールドでを見つけて、属性DescriptionAttributeを取得する必要があります。Description

return enumType.GetFields()
                .Select(f => (DescriptionAttribute)f.GetCustomAttribute(typeof(DescriptionAttribute)))
                .Where(a => a != null)
                .Select(a => a.Description)

フィールドに複数の説明がある場合は、次のようにすることができます。

FieldInfo[] fields = enumType.GetFields();
foreach(FieldInfo field in fields)
{
    var descriptionAttributes = field.GetCustomAttributes(false).OfType<DescriptionAttribute>();
    foreach(var descAttr in descriptionAttributes)
    {
        yield return descAttr.Description;
    }
}

これは、既存のアプローチに似ています。

于 2013-06-02T19:31:25.043 に答える
0

これで問題を解決できると思います。実装されていない場合はnull、または例外を返すことができます。何が必要かによります。

public DescriptionAttribute GetDescription(ContractorType contractorType)
{
     MemberInfo memberInfo = typeof(ContractorType).GetMember(contractorType.ToString())
                                          .FirstOrDefault();

     if (memberInfo != null)
    {
         DescriptionAttribute attribute = (DescriptionAttribute) 
                 memberInfo.GetCustomAttributes(typeof(DescriptionAttribute), false)
                           .FirstOrDefault();
         return attribute;
    }

    //return null;
    //or

    throw new NotImplementedException("There is no description for this enum");
}

したがって、次のように使用します。

DescriptionAttribute attribute = GetDescription(ContractorType.RECIPIENT);

あなたの質問を読んでいませんでした。すべての説明文字列を取得するために使用できるコードを次に示します。

 public IEnumerable<string> GetAllDescriptionInText()
 {
     List<string> descList = new List<string>();
     foreach (DescriptionAttribute desc in Enum.GetValues(typeof(DescriptionAttribute)))
     {
         descList.Add(GetDescription(desc).Value);
     }
     return descList;
 }
于 2013-06-02T19:25:23.557 に答える
0

これを試すことができます

public string ContractorTypeDescription(Enum ContractorType)
{
    FieldInfo fi = ContractorType.GetType().GetField(ContractorType.ToString());
    var attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
    if (attributes.Length > 0)
    {
        return attributes[0].Description;
    }
    else
    {
        return ContractorType.ToString();
    }
}
于 2013-06-02T19:30:50.850 に答える
0

これはリストではなく辞書
ですが、私が使用するものです

using System.ComponentModel;
using System.Reflection;
using MyExtensions;

namespace MyExtensions
{
    public static class Extension
    {
        public static string GetDescriptionName(this Enum value)
        {
            Type type = value.GetType();
            string name = Enum.GetName(type, value);
            if (name == null)
                return null;
            else
            {
                FieldInfo field = type.GetField(name);
                if (field == null)
                    return name;
                else
                {
                    DescriptionAttribute attr =
                            Attribute.GetCustomAttribute(field,
                                typeof(DescriptionAttribute)) as DescriptionAttribute;
                    if (attr == null)
                        return name;
                    else
                        return attr.Description;
                }
            }
        }
    }
}

namespace EnumDescription
{
    class Program
    {
        public enum enumDateCond : byte 
        {
            [Description("Empty")]
            Null = 0,
            [Description("Not Empty")]
            NotNull = 1,
            EQ = 2, 
            LT = 3, 
            LE = 4, 
            GE = 14, 
            GT = 15 
        };
        static void Main(string[] args)
        {
            enumDateCond x = enumDateCond.Null;
            string description = x.GetDescriptionName();
            foreach (enumDateCond enm in Enum.GetValues(typeof(enumDateCond)))
            {
                description = enm.GetDescriptionName();
                Console.WriteLine(description);
            }
            Console.WriteLine("Dictionary");
            Dictionary<enumDateCond, string> DLenumDateCond = EnumToDictionary<enumDateCond>();
            foreach(enumDateCond key in DLenumDateCond.Keys)
            {
                Console.WriteLine(key.ToString() + " " + DLenumDateCond[key]);
            }
        }
        public static Dictionary<T, string> EnumToDictionary<T>()
            where T : struct
        {
            Type enumType = typeof(T);

            // Can't use generic type constraints on value types,
            // so have to do check like this
            if (enumType.BaseType != typeof(Enum))
                throw new ArgumentException("T must be of type System.Enum");

            Dictionary<T, string> enumDL = new Dictionary<T, string>();
            foreach (T enm in Enum.GetValues(enumType))
            {
                string name = Enum.GetName(enumType, enm);
                if (name != null)
                {
                    FieldInfo field = enumType.GetField(name);
                    if (field != null)
                    {
                        DescriptionAttribute attr =
                                Attribute.GetCustomAttribute(field,
                                    typeof(DescriptionAttribute)) as DescriptionAttribute;
                        if (attr != null)
                            name = attr.Description;
                    }
                }
                enumDL.Add(enm, name);
            }
            return enumDL;
        }
    }
}
于 2014-03-20T23:04:56.190 に答える