C#,动态linq错误“类型”字符串中不存在适用的方法“包含”

时间:2018-11-21 15:09:15

标签: c# linq dynamic-linq

我有一个这样的对象列表(我正在使用.NET 3.5)

var dt = getResultTable(...);

var value1 = dt.Rows[0].GetValue<int>("ColumnName");

var value2 = dt.Rows[0].GetValue<int>("ColumnName", 10); // you can also specify a different default value if needed

现在,我尝试使用Linq在列表中进行搜索。 这按预期工作

public class MyObjects
{
    public object Name { get; set; }
    public bool Case { get; set; }
}

List<MyObjects> test = new List<MyObjects> { 

    new MyObjects { Name = "one" },
    new MyObjects { Name = "two" },
    new MyObjects { Name = "three" },
    new MyObjects { Name = "four" },
    new MyObjects { Name = "one1" },
    new MyObjects { Name = "two1" },
    new MyObjects { Name = "three1" },
    new MyObjects { Name = "four1" },
    new MyObjects { Name = "one2" },
    new MyObjects { Name = "two2" },
    new MyObjects { Name = "three2" },
    new MyObjects { Name = "four2" },
};

使用动态Linq,这也可以按预期工作

var tmp = test
    .Select(p => p.Name)
    .Where(x => x.ToString().Contains("One", StringComparison.InvariantCultureIgnoreCase))
    ;

但是,当尝试使用区分大小写(不区分大小写)时,动态操作会失败。

var dtmp = test.AsQueryable()
    .Select(p => p.Name)
    .Where("ToString().Contains(@0)", "one")
    ;

错误是

var dtmp2 = test.AsQueryable()
    .Select(p => p.Name)
    .Where("ToString().Contains(@0, @1)", "one", StringComparison.InvariantCultureIgnoreCase)
    ;

我的第一个尝试是编写一个这样的Contains()扩展名

No applicable method 'Contains' exists in type 'String'

似乎Dynamic Linq不知道我的扩展名。我发现了(据此) https://social.msdn.microsoft.com/Forums/en-US/39763339-1700-486f-9800-badd257e921e/custom-extension-methods-and-dynamic-linq-dynamic-expression-api?forum=linqprojectgeneral

Dynamic Linq无法非常轻松地使用(静态)扩展的

所以:

  1. 以常规方法转换扩展名。但是,如何为每个ToString()做到这一点,是否有可能还是应该在MyObject中编写一个方法,然后对特定对象使用linq?

  2. 修改动态库代码以接受硬编码的(my)静态扩展。

  3. 其他建议?

注意:我可以使用简单的if / else区分大小写,并具有两种动态效果,但由于我的应用程序使用了一些复杂的过滤功能,因此我更喜欢解决动态方式。

先谢谢您

2 个答案:

答案 0 :(得分:1)

如果您的应用程序需要动态过滤器功能,则建议调用者传递一个谓词。

这可以将关注点分离并简化单元测试。

此外,当调用者传递谓词时,不需要IF / ELSE语句。

var predicate = new Predicate<string>(str => str.Contains("one"));

var tmp = test.Select(p => p.Name).Where(predicate);

答案 1 :(得分:0)

您尝试使用System.Linq.Dynamic.Core是因为该库似乎可以处理您的示例C#代码。

相关问题