在代码中使用动态对象创建了 LINQ 查询
本文关键字:创建 LINQ 查询 对象 动态 代码 | 更新日期: 2023-09-27 18:30:58
我尝试在 LINQ 查询中使用扩展对象,以便能够查询运行时创建的属性,例如 csv 文件中的标头。如果直接在代码中键入 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 代码时会出现错误: CS1963:表达式树可能不包含动态操作。
查询的代码使用以下行创建:
doRequestMethod.Statements.Add(new CodeMethodReturnStatement(new CodeSnippetExpression(Query)));
我想codedom编译器正在以某种方式构建表达式树,这与解析LINQ查询中的直接类型的方式不同。任何使其工作的想法都将得到满足,包括为运行时生成的对象动态创建查询的其他想法。
为了得到你得到的错误,我必须修复 LINQ 编译器以支持dynamic
,告诉它使用 C# 4.0 并添加对 Microsoft.CSharp.dll 的引用,所以我假设你也做了同样的事情。
问题是 LINQ 编译器中的源可以是任何集合,包括 IQueryable<T>
。如果IQueryable<T>
应该正常工作,您实际上需要将其视为 IQueryable<T>
,而不是IEnumerable<T>
.LINQ 编译器解决此问题的方法是,它使用 AsQueryable()
扩展方法将任何源视为IQuerybale<T>
。
这意味着生成的代码如下所示:
public object DoRequest(System.Linq.IQueryable<System.Dynamic.ExpandoObject> hans) {
return from dynamic x in hans where x.ID < 3 select x;
}
此代码的问题在于尝试使用IQuerybale<T>
版本的 LINQ 方法,这些版本使用 Expression
s。而且,正如错误消息告诉您的那样,Expression
不支持dynamic
。
我认为解决此问题的最简单方法是修改 LINQ 编译器以使用 IEnumerable<T>
,而不是通过将AddSource()
更改为IQuerybale<T>
:
public void AddSource<T>(string name, IEnumerable<T> source)
{
this.sources.Add(new SourceDescription(name, typeof(IEnumerable<T>), source));
}
当然,这意味着它不适用于数据库查询,但无论如何您都不能使数据库查询适用于dynamic
。