c# - 在 codedom 中使用动态对象创建 LINQ 查询

标签 c# linq codedom expandoobject

我尝试在 LINQ 查询中使用 expandoobjects 以能够查询在运行时创建的属性,例如来自 csv 文件的 header 。如果像示例中那样直接在代码中键入 LINQ 查询,则一切正常:

// initialize testdata
List<ExpandoObject> hans = new List<ExpandoObject>();
string[] names = {"Apfel", "Birne", "Banane", "Orange"};
int[] ids = { 1, 2, 3, 4 };
for (int i = 0; i < 4; i++)
{
   dynamic horst = new ExpandoObject();
   ((IDictionary<string, object>)horst).Add("Fruit", names[i]);
   ((IDictionary<string, object>)horst).Add("ID", ids[i]);
   hans.Add(horst);
}

// try some LINQ queries, both are working as intended
var klaus = from dynamic x in hans where x.ID < 3 select x;
//var klaus = hans.Where(x => x.ID < 3).Select(x => x);

然后我尝试从命令行读取查询并使用评估 linq 编译器的轻微修改版本创建动态 LINQ 查询。

string expression = System.Console.ReadLine();
LinqCompiler lc = new LinqCompiler(expression);
lc.AddSource<ExpandoObject>("hans", hans);
IEnumerable<ExpandoObject> klaus = (IEnumerable<ExpandoObject>)lc.Evaluate();

只要我不使用 WHERE 或 ORDER BY 语句,一切都很好,但如果查询中包含任何 WHERE 或 ORDER BY,我在 linq 编译器中编译 codedom 代码时会出错:< em>CS1963:表达式树不能包含动态操作。

查询代码是使用以下行创建的:

doRequestMethod.Statements.Add(new CodeMethodReturnStatement(new CodeSnippetExpression(Query)));

我假设 codedom 编译器构建表达式树的方式与解析直接键入 LINQ 查询的方式不同。任何使它起作用的想法都会受到赞赏,包括其他为运行时生成的对象动态创建查询的想法。

最佳答案

为了得到你得到的错误,我必须修复 LINQ Compiler支持dynamic ,通过告诉它使用 C# 4.0 并添加对 Microsoft.CSharp.dll 的引用,所以我假设你也做了同样的事情。

问题是 LINQ 编译器中的源可以是任何集合,包括 IQueryable<T> .如果IQueryable<T>应该可以正常工作,您实际上需要将其视为 IQueryable<T> , 不是 IEnumerable<T> . LINQ 编译器解决此问题的方法是将任何 源视为IQuerybale<T>通过使用 AsQueryable()扩展方法。

这意味着生成的代码如下所示:

public object DoRequest(System.Linq.IQueryable<System.Dynamic.ExpandoObject> hans) {
    return from dynamic x in hans where x.ID < 3 select x;
}

此代码的问题在于尝试使用 IQuerybale<T>使用 Expression 的 LINQ 方法版本秒。而且,正如错误消息告诉您的那样,Expression不支持dynamic .

我认为解决此问题的最简单方法是修改 LINQ 编译器以使用 IEnumerable<T> , 而不是 IQuerybale<T>通过更改 AddSource()进入:

public void AddSource<T>(string name, IEnumerable<T> source) 
{
    this.sources.Add(new SourceDescription(name, typeof(IEnumerable<T>), source));
}

当然,这意味着它不能很好地用于数据库查询,但是您不能使数据库查询与dynamic 一起工作。无论如何。

关于c# - 在 codedom 中使用动态对象创建 LINQ 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10109961/

相关文章:

c# - 动态用户控件更改 - WPF

c# - 在 azure 上发布时列名无效

c# - 使用 WPF 和 Entity Framework 将查询绑定(bind)到数据网格

C# - Cookie 管理

c# - NAudio 演示不再有效

c# - 是否可以设置 Visual Studio 2017,使其在远程 Linux 机器而不是本地机器上运行和调试 .NET Core C# 应用程序?

c# - 使用 CodeDom 从外部类调用方法

c# - 使用 Where 子句将 csv 值读入字典

c# - visual studio 2010 c# winforms运行时编译

c# - 高性能的属性访问和可能的动态编译