繁体   English   中英

LINQ查询中的怪异扩展方法行为

[英]Weird extention method behaviour in LINQ query

我有一个自定义属性,用于存储枚举项的显示名称。 我编写了一个Extension方法,该方法返回Enum自定义属性显示名称。

我在LINQ查询中使用扩展方法。 但是输出很奇怪。 当我在尚未运行的查询中调用我的扩展方法时,它返回Enum is null但是当我在查询中运行.ToList() ,它运行正常(请参见输出)……两者之间的区别是什么他们? 为什么查询不运行时enum为null。

注意:我是LINQPAD

void Main()
{
    Console.WriteLine(((ProductStatuses)0).GetTitle());
    Console.WriteLine(((ProductStatuses)1).GetTitle());
    Console.WriteLine(((ProductStatuses)3).GetTitle());

    var query_01 = (from item in SH_Products
                    select new
                    {
                        Status = item.Status,
                        StatusText = ((ProductStatuses)item.Status).GetTitle(),
                    });

    var query_02 = (from item in SH_Products.ToList()
                    select new
                    {
                        Status = item.Status,
                        StatusText = ((ProductStatuses)item.Status).GetTitle(),
                    });

    query_01.Dump();
    query_02.Dump();
}

public static class ExtensionMethods
{
    public static string GetTitle(this Enum enm)
    {
        if (enm == null)
        {
            return "Enum is null";
        }

        var type = enm.GetType();
        var members = type.GetMembers(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static);

        foreach (var item in members)
        {
            if (enm.ToString() == item.Name)
            {
                var attributes = item.GetCustomAttributes(typeof(FaraDisplay), false);

                var attribute = String.Empty;
                if (attributes.Length == 0)
                    attribute = item.Name;
                else
                    attribute = ((FaraDisplay)attributes.Single()).GetName();

                return attribute;
            }
        }

        throw new InvalidEnumArgumentException();
    }
}

public enum ProductStatuses
{
    [FaraDisplay("Inactive Product")]
    Inactive = 0,
    [FaraDisplay("Available Product")]
    Available = 1,
    [FaraDisplay("ComingSoon Product")]
    ComingSoon = 2,
    [FaraDisplay("UnAvailable Product")]
    UnAvailable = 3,
    [FaraDisplay("OrderRegister Product")]
    OrderRegister = 4
}

[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
public class FaraDisplay : Attribute
{
    private readonly string _name;

    public FaraDisplay(string name)
    {
        _name = name;
    }

    public string GetName()
    {
        return _name;
    }
}

输出:

无效产品
可用产品
不可用的产品

枚举为空
枚举为空
枚举为空
枚举为空

无效产品
可用产品
不可用的产品
不可用的产品

实际上,问题是linq to sql不知道如何将GetTiltle()转换为sql语句,因此它跳过了它。 当您调用ToList() ,您正在使用linq来处理对象,因此它可以按预期工作,因为那时候它只是普通的.net。

所有linq提供程序(实体框架,nhibernate等)都具有相同的问题,尽管您会看到实体框架抛出异常,也许还会抛出nhibernate。

没有基于您正在做的事情的解决方法,因此一旦将对象存储在内存中,就只需要执行该计算即可。

在Linq查询中,您不应该使用方法调用,而应该首先获取值,然后在linq查询中进行赋值,我认为Darren是正确的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM