Tag: expression

动态LINQ,选择函数,适用于Enumerable,但不适用于Queryable

我一直在摆弄动态LINQ一段时间了,但我还没有了解它的秘密。 我有一个我要解析的表达式,如下所示: “document.LineItems.Select(i => i.Credit).Sum();” 在解析这个问题时,我需要在LineItems Collection上调用Select函数。 我正在使用Expression.Call的工厂方法: Expression.Call( typeof(Queryable), “Select”, new Type[] { typeof(LineItem), typeof(decimal?) }, expr, Expression.Lambda(expression, new ParameterExpression[] { Expression.Parameter(typeof(LineItem) })); 此刻 expr: document.LineItems [ICollection] expression: LineItem.Credit [decimal?] 这些都没有实现。 我现在正在构建表达式树。 现在,问题是: 这个Expresssion.Call抛出和exception:“没有generics方法’选择’类型’System.Linq.Queryable’与提供的类型参数和参数兼容”; 我通过改变Expression.Call的第一个参数,通过在’System.Linq.Enumerable’而不是’Queryable’中查找’Select’来轻松解决它。 但是,这并不是我想要的。 我不希望所有LineItem都只计算Sum(),这显然是Enumerable的情况。 我想要Queryable工作。 另外,对于解析的最后一部分 – Sum(),我还需要使用Enumerable Sum(),因为Queryable Sum()会抛出相同的Exception。 我已经检查了MSDN,“选择”function的两个签名是相同的,所以我真的不明白为什么一个工作而另一个不工作。 任何帮助或指针都会受到重视。 问候,

使用具有IEnumerable的Lambda表达式树

我一直在努力学习更多关于使用Lamba表达式树的知识,因此我创建了一个简单的例子。 这是代码,如果作为C#程序粘贴,这可以在LINQPad中使用。 void Main() { IEnumerable list = GetUsers().Where(NameContains(“a”)); list.Dump(“Users”); } // Methods public IEnumerable GetUsers() { yield return new User{Name = “andrew”}; yield return new User{Name = “rob”}; yield return new User{Name = “chris”}; yield return new User{Name = “ryan”}; } public Expression<Func> NameContains(string namePart) { return u => u.Name.Contains(namePart); } // Classes public […]

使用多个属性构建动态GroupBy选择器表达式树

我将为GroupBy构建一个动态表达式树。 我想要实现的就是这样。 var NestedGrouped = listOfPerson.GroupByMany(x => x.Name,x=>x.Age).ToList(); 我的人员类似: – class Person { public string Name{ get; set; } public int Age{ get; set; } public float Salary{ get; set; } } public class GroupResult { public object Key { get; set; } public int Count { get; set; } public IEnumerable Items { get; […]

如何在没有编译的情况下从现有的LambdaExpression构建LambdaExpression

我想结合两个LambdaExpressions而不编译它们。 这就是我编译它们时的样子: public Expression<Func> CreatePredicate( Expression<Func> getMemberExpression, Expression<Func> memberPredicateExpression) { return x => memberPredicateExpression.Compile()(getMemberExpression.Compile()(x)); } 这显然不是从提供的参数中获取目标表达式的最快方法。 此外,它使它与不支持C#方法调用的LINQ to SQL等查询提供程序不兼容。 从我所看到的,似乎最好的方法是构建一个ExpressionVisitor类。 然而,这似乎是一个非常常见的任务。 有没有人知道提供这种function的现有开源代码库? 如果没有,那么接近ExpressionVisitor以使其尽可能通用的最佳方法是什么?

C#:编译表达式时,已添加具有相同键的项

好的,这是一个棘手的问题。 希望这里有一位表达大师可以发现我在这里做错了什么,因为我只是没有得到它。 我正在构建用于过滤查询的表达式。 为了简化这个过程,我有一些Expression<Func>扩展方法,这些方法使我的代码更清晰,到目前为止它们已经很好地工作了。 我已经为所有人编写了测试,除了一个,我今天写了一个。 并且该测试完全失败,带有长堆栈跟踪的ArgumentException 。 我只是不明白。 特别是因为我在查询中成功使用了该方法一段时间了! 无论如何,这是运行测试时得到的堆栈跟踪: failed: System.ArgumentException : An item with the same key has already been added. at System.ThrowHelper.ThrowArgumentException(ExceptionResource resource) at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add) at System.Linq.Expressions.ExpressionCompiler.PrepareInitLocal(ILGenerator gen, ParameterExpression p) at System.Linq.Expressions.ExpressionCompiler.GenerateInvoke(ILGenerator gen, InvocationExpression invoke, StackType ask) at System.Linq.Expressions.ExpressionCompiler.Generate(ILGenerator gen, Expression node, StackType ask) at System.Linq.Expressions.ExpressionCompiler.GenerateBinary(ILGenerator gen, […]

在翻译LINQ表达式时,C#编译器如何选择SelectMany?

Enumerable.SelectMany有4个重载签名。 为简单起见,我们忽略了带有int参数的两个签名。 所以我们有4个SelectMany签名: public static IEnumerable SelectMany( this IEnumerable source, Func<TSource, IEnumerable> selector ) public static IEnumerable SelectMany( this IEnumerable source, Func<TSource, IEnumerable> collectionSelector, Func resultSelector ) 我的问题是:在将LINQ表达式转换为扩展方法调用时,C#编译器如何选择SelectMany? 基本上,如果LINQ表达式中有多个from ,则会有SelectMany。 但是,似乎C#编译器只选择第二个签名。 永远不会使用第一个签名。 IEnumerable en1 = Enumerable.Range(1, 3); IEnumerable en2 = new double[] { 1.0, 3.14 }; IEnumerable en3 = from i1 in en1 from i2 […]

Expression.Compile与Lambda的性能,直接与虚拟调用

我很好奇Expression.Compile与代码中的lambda表达式和直接方法使用方式的性能如何,以及直接方法调用与虚方法调用(伪代码): var foo = new Foo(); var iFoo = (IFoo)foo; foo.Bar(); iFoo.Bar(); (() => foo.Bar())(); (() => iFoo.Bar())(); Expression.Compile(foo, Foo.Bar)(); Expression.Compile(iFoo, IFoo.Bar)(); Expression.CompileToMethod(foo, Foo.Bar); Expression.CompileToMethod(iFoo, IFoo.Bar); MethodInfo.Invoke(foo, Foo.Bar); MethodInfo.Invoke(iFoo, IFoo.Bar);