【问题标题】:Dynamic lambda expression for where clausewhere 子句的动态 lambda 表达式
【发布时间】:2017-05-29 06:36:46
【问题描述】:

我有一个动态的对象列表,我使用 lambda 表达式 where 子句过滤项目。例如,只要考虑它有 3 个属性,foo、bar 和 baz

class item // let this be current class in dynamic item list
{
    bool foo;
    string bar;
    string baz;
}

现在如果我想过滤 foo 为 false 的项目列表,我可以使用以下表达式

var filtered = itemList.Where("!foo");

我什至可以按字符串值过滤列表

var filtered = itemList.Where("bar==\"value\""); \\all items with bar = value

我要实际检查的是列表中的项目是否具有特定的字符串值,而不是空白的空值。我尝试了以下代码

var filtered = itemList.Where("!String.IsNullOrWhiteSpace(baz)");

报错了

'System.Func`2[DynamicType,System.Object]' 类型的表达式不能 用于方法“Boolean”的“System.String”类型参数 IsNullOrWhiteSpace(System.String)'

虽然我通过以下查询成功获得了结果

var filtered = itemList.Where("baz!=null && baz!=\"\"");

我想确认是否可以在此查询中使用String.IsNullOrWhiteSpace()

【问题讨论】:

  • 您正在更改字符串值,因此只需将字符串设为变量而不是硬编码。
  • @jdweng,对不起,我没听懂你在说什么。我只是想知道为什么String.IsNullOrWhiteSpace() 不起作用

标签: c# dynamic lambda dynamic-linq


【解决方案1】:

您可以将“!String.IsNullOrWhiteSpace(baz)”替换为“!(baz == null || baz.Trim() == string.Empty)”,它应该可以工作。

【讨论】:

  • 我只是输入了这个例子来展示一个场景,修剪很好,我想知道的是为什么String.IsNullOrWhiteSpace(baz)有问题
  • 这是一个字符串,因为 if 在双引号中。所以你不能这样做:string myString = "!String.IsNullOrWhiteSpace(baz)";
  • 我的理解是,Linq 在执行之前会将所有内容都转换为 SQL。 SQL 中无法识别的任何函数都将不起作用。
  • @AndyIZ 仅当它是 Linq-to-Entities 或 Linq-to-SQL 或类似的。 Linq-to-objects 与 SQL 无关,据我了解,作者使用带有普通 Linq-to-objects 的动态 LINQ。
  • 所以,跟动态类型的查询无关,和你们讨论的翻译有关。我今天发现了这个 stackoverflow.com/questions/9606979/… ,这里 OP 使用的是普通的 LINQ 查询并且遇到了和我一样的问题。但是,是的,他正在使用 LINQ to SQL。
【解决方案2】:

看看System.Linq.Dynamic,有一个很棒的example here

您还需要确保 List<T> 不是 List<object>,否则 System.Linq.Dynamic 将无法找到属性。

这是您的示例的 sn-p:

void Main()
{
    var itemList = new List<dynamic>{ new {foo = true, bar = "a", baz = "b" }, new {foo = true, bar = (string)null, baz = "d" } };
    var filtered = itemList.ToAnonymousList().Where("bar != null and bar !=\"\"");
    filtered.Dump();
}

public static class EnumerableEx {
    public static IList ToAnonymousList(this IEnumerable enumerable)
    {
        var enumerator = enumerable.GetEnumerator();
        if (!enumerator.MoveNext())
            throw new Exception("?? No elements??");

        var value = enumerator.Current;
        var returnList = (IList) typeof (List<>)
            .MakeGenericType(value.GetType())
            .GetConstructor(Type.EmptyTypes)
            .Invoke(null);

        returnList.Add(value);

        while (enumerator.MoveNext())
            returnList.Add(enumerator.Current);

        return returnList;
    }
}

【讨论】:

    【解决方案3】:

    使用您的表达方式我没有问题 - 效果很好。

    我已经将它与对象和实体一起用于 EF 存储。

    'System.Func`2[DynamicType,System.Object]' 类型的表达式不能 用于方法“Boolean”的“System.String”类型参数 IsNullOrWhiteSpace(System.String)'

    所以查看错误,它说明(移动顺序):

    返回Boolean 的方法IsNullOrWhiteSpace 需要System.String 类型的参数。 但是收到的是Expression of type System.Func``2[DynamicType,System.Object]'

    看来您可能引用了一个对象而不是一个字符串值来进行比较。但是,如果没有您正在使用的对象的示例代码,以及您使用的是对象、实体还是 LinQ to SQL(我没有尝试过),我们只能猜测您为表达式提供的内容。

    最后,什么是

    '动态项目列表'?

    你用的是Dynamic,还是普通的List&lt;Item&gt;

    【讨论】:

    • 动态的,不是普通的List
    猜你喜欢
    • 1970-01-01
    • 2010-12-17
    • 1970-01-01
    • 2011-10-03
    • 1970-01-01
    • 1970-01-01
    • 2017-10-10
    • 2014-02-01
    • 1970-01-01
    相关资源
    最近更新 更多