是否可以从字符串重构委托? C#.NET核心

时间:2018-10-04 16:29:37

标签: c# string parsing delegates

我试图在C#.NET Core中制作一对程序,其中一个程序以文本形式(XML,JSON等)生成“模板”或“规则”,另一个将其转换为代码以跑。这仍处于可行性阶段,因此我愿意接受所有建议。我的具体问题涉及到代表的重建:

是否可以读取字符串,例如“ x => x [1]> 0”,然后将其转换为要在Linq中使用的委托?例如可以:

string myRule = "x => x[1] >= 18";

以某种方式用于:

// for the example's sake, assume the following table has a fixed structure of "id, age" 
List<List<double>> myList = new List<List<double>>()
{
    new List<double>(){ 1, 25 },
    new List<double>(){ 2, 14 },
    new List<double>(){ 3, 30 }
};

int adults = myList.Count(StringToDelegate(myRule));
Console.WriteLine("Total adults " + adults);

是否存在可以使这项工作有效的“ StringToDelegate”?

请注意,创建字符串的软件和需要使用它们的软件都是预先知道所需的委托类型(在这种情况下为“ Func ,bool>”)。

谢谢!

1 个答案:

答案 0 :(得分:0)

多亏了Amir Popovich的初次指点,我得以(几个小时后)找到了答案。由于不是很简单,我将把所有详细信息放在这里,以供将来需要的人(包括我自己)。

不幸的是,罗斯林方法(此处https://www.strathweb.com/2018/01/easy-way-to-create-a-c-lambda-expression-from-a-string-with-roslyn/描述)虽然开箱即用,但非常慢。我在编译第一个表达式时经历了大约2600毫秒的开销,此后每个表达式则花费了100毫秒。但是,在该页面的评论中,一个JochenKühner指出了System.Linq.Dynamic.Core软件包(https://github.com/StefH/System.Linq.Dynamic.Core)的存在,该软件包可以完成相同的工作。但是,这开箱即用,甚至文档中的示例也产生了错误。经过一番研究,我意识到NuGet可用的软件包中存在一个问题,一位Paritosh指出,还需要直接向我的项目中添加文件的较新版本(请参见Linq Dynamic ParseLambda not resolving)。

因此,基本上要使其正常工作(至少在.NET Core中),您需要:

1)将NuGet System.Linq.Dynamic.Core添加到您的项目中。

2)转到以下链接,并从Microsoft获得CSharpSamples.zip:

https://msdn.microsoft.com/en-us/vstudio/bb894665.aspx?f=255&MSPPError=-2147217396

3)找到文件LinqSamples \ DynamicQuery \ DynamicQuery \ Dynamic.cs并将其复制到您自己的项目中。

使用上述方法,您应该拥有一个工作环境。然后,如果您包括以下内容:

using System;
using System.Linq;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Linq.Dynamic;

您可以编写如下代码:

List<List<double>> myList = new List<List<double>>()
{
    new List<double>(){ 1, 25 },
    new List<double>(){ 2, 14 },
    new List<double>(){ 3, 30 }
};

ParameterExpression[] x = new ParameterExpression[] { Expression.Parameter(typeof(List<double>), "x") };
Func<List<double>, bool> adultFilter = (Func<List<double>, bool>) System.Linq.Dynamic.DynamicExpression.ParseLambda(x, null, "x[1] > 18").Compile();
int adults = myList.Count(adultFilter);
Console.WriteLine("Total adults " + adults);

请注意,Linq.Expression和Link.Dynamic中都存在一个DynamicExpression类,因此需要提供完整的引用并需要额外的一行。另外请注意,以上代码大约需要30ms的时间来编译和运行,而第一个表达式没有额外的开销。

您可以在此处找到有关如何使用Linq.Dynamic库的更多详细信息(尽管作者声称Wiki的准确率仅为80%)

https://github.com/StefH/System.Linq.Dynamic.Core/

我希望有一天NuGet软件包将得到修复,Wiki也将得到改善,但是在此之前,这些注释可能会对您有所帮助!