“MyEnum”类型的表达式不能用于类型的参数

时间:2013-02-01 17:18:49

标签: c# linq enums extension-methods

我为我的枚举创建了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)'

3 个答案:

答案 0 :(得分: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();
    }
}

我添加了一个私有的泛型类来缓存枚举成员的描述,以避免大量运行时使用反射。它看起来有点奇怪弹出进出第一个缓存然后检索值,但它应该工作正常:)

我在this answer中发出的警告仍然适用 - 传递给字典的枚举值未经过验证,因此您可以通过调用((MyEnum)5367372).ToFrendlyString()使其崩溃。

答案 1 :(得分:0)

我不确定但是你可能还没有将DAL项目添加到你当前的项目中(添加参考 - &gt; solutins中的项目 - &gt; Dal)。然后它可能会工作。 (我有一个类似的问题,这是我的解决方案)

答案 2 :(得分:0)

问题似乎是您的收藏集是IQueryable<T>,而查询提供商正在尝试将您的Select()转换为查询字符串。

避免这种情况的一种方法是使用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();