2

列挙型の Enum ToFrendlyString 関数を作成しましたが、Linq では使用できません。

 public enum MyEnum
    {

        Queued = 0,           
        [Description("In progress")]
        In_progress = 2,            
        [Description("No answer")]
        No_answer = 6,

    }



  public static class EnumToFrendlyString
    {

        public static string ToFrendlyString(this Enum value)
        {
            return value.GetEnumDescription();
        }


        public static string GetEnumDescription(this Enum value)
        {
            FieldInfo fi = value.GetType().GetField(value.ToString());

            var attributes =
                (DescriptionAttribute[])fi.GetCustomAttributes(
                    typeof(DescriptionAttribute),
                    false);

            if (attributes.Length > 0)
                return attributes[0].Description;

            return value.ToString();
        }
    }

Linqでこの関数を使用しようとすると、エラーが発生します

  var res = collection.AsQueryable().Where(p => p.UserID == UserID).OrderByDescending(p=> p.DateCreated).Select(p => new MyClass
                {                          
                     Date = p.DateCreated.ToString(),
                     Status = p.Status.ToFrendlyString(),                        
                }).Take(10).ToList();

同じクラスで別の関数を作成すると、

 private string MyStatusToString(MyEnum status)
       {
           return status.ToFrendlyString();
       }

この関数を使用するようにLinqを変更すると、すべてが機能します。

エラー

Expression of type 'DAL.MyEnum' cannot be used for parameter of type 'System.Enum' of method 'System.String ToFrendlyString(System.Enum)'
4

3 に答える 3

2

Enumそのような拡張メソッドのタイプとして使用できるかどうかはわかりません。代わりにこれを試してください。私はコードを少し整理する自由を取りました、それらの変更を無視してください:)

public static class EnumToFrendlyString
{
    public static string ToFrendlyString<T>(this T value)
        where T : struct
    {
        return value.GetEnumDescription();
    }

    public static string GetEnumDescription<T>(this T value)
        where T : struct
    {
        return EnumDescriptionCache<T>.Descriptions[value];
    }

    private static class EnumDescriptionCache<T>
        where T : struct
    {
        public static Dictionary<T, string> Descriptions =
            Enum.GetValues(typeof(T))
                .Cast<T>()
                .ToDictionary(
                    value => value,
                    value => value.GetEnumDescriptionForCache());
    }

    private static string GetEnumDescriptionForCache<T>(this T value)
        where T : struct
    {
        if (!typeof(T).IsEnum)
        {
            throw new ArgumentException("Only use with enums", "value");
        }

        var descriptionAttribute = typeof(T)
            .GetField(value.ToString())
            .GetCustomAttributes(typeof(DescriptionAttribute), false)
            .Cast<DescriptionAttribute>()
            .FirstOrDefault();

        return (descriptionAttribute != null)
            ? descriptionAttribute.Description
            : value.ToString();
    }
}

プライベートなジェネリッククラスを追加して、列挙型メンバーの説明をキャッシュし、実行時にリフレクションを頻繁に使用しないようにしました。最初にキャッシュしてから値を取得するためにクラスに出入りするのは少し奇妙に見えますが、正常に機能するはずです:)

この回答で示した警告は引き続き適用されます。ディクショナリに渡された列挙値は検証されていないため、を呼び出すとクラッシュする可能性があります((MyEnum)5367372).ToFrendlyString()

于 2013-02-01T18:04:17.533 に答える
0

よくわかりませんが、現在のプロジェクトにまだDALプロジェクトを追加していない可能性があります(参照の追加->solutinsのプロジェクト->Dal)。その後、それは動作する可能性があります。(私は一度同様の問題を抱えていましたが、これが私の解決策でした)

于 2013-02-01T17:38:35.527 に答える
0

問題は、あなたのコレクションがIQueryable<T>あり、クエリ プロバイダーがあなたSelect()をクエリ文字列に変換しようとしていることです。

これを回避する 1 つの方法は、次をSelect()使用してメモリ内で実行することIEnumerable<T>です。

var res = collection.AsQueryable()
            .Where(p => p.UserID == UserID)
            .OrderByDescending(p=> p.DateCreated)
            .Take(10)
            .AsEnumerable()
            .Select(p => new MyClass
            {                          
                 Date = p.DateCreated.ToString(),
                 Status = p.Status.ToFrendlyString(),                        
            })
            .ToList();
于 2013-02-01T19:07:29.707 に答える