在codedom中使用动态对象创建了LINQ查询

时间:2012-04-11 16:24:06

标签: c# linq codedom expandoobject

我尝试在LINQ查询中使用expandoobjects,以便能够查询在运行时创建的属性,例如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编译器中的编码时代码时会出错:< em> CS1963:表达式树可能不包含动态操作。

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

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

我认为codedom编译器正在构建表达式树,其方式与解析LINQ查询中直接键入的方式不同。任何使这个工作起作用的想法都会受到欢迎,包括为运行时生成的对象动态创建查询的其他想法。

1 个答案:

答案 0 :(得分:2)

要获得您遇到的错误,我必须修复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>版本的LINQ方法,使用Expression s。并且,正如错误消息所示,Expression不支持dynamic

我认为解决此问题的最简单方法是将IEnumerable<T>更改为IQuerybale<T>,而不是AddSource()来修改LINQ编译器以使用public void AddSource<T>(string name, IEnumerable<T> source) { this.sources.Add(new SourceDescription(name, typeof(IEnumerable<T>), source)); }

dynamic

当然,这意味着它不适用于数据库查询,但无论如何都无法使数据库查询与{{1}}一起使用。