Reputation: 5155
I want to extend the LINQ expression (DoSomething)
using LinqKit; // for System.Linq.Expressions.Expression<>.Invoke()
public class Expressions
{
public static System.Linq.Expressions.Expression<
System.Func<int, int, int, int, bool>>
DoSomething =
(a, b, c, d) => false;
}
public class ExpressionTester
{
public ExpressionTester()
{
Expressions.DoSomething.Invoke(1, 2, 3, 4);
}
}
with an additional parameter but it does not compile:
public class Expressions
{
public static System.Linq.Expressions.Expression<
System.Func<int, int, int, int, int, bool>>
DoSomething =
(a, b, c, d, e) => false;
}
public class ExpressionTester
{
public ExpressionTester()
{
Expressions.DoSomething.Invoke(1, 2, 3, 4, 5);
}
}
The best overloaded method match for 'System.Linq.Expressions.Expression.Invoke(System.Linq.Expressions.Expression, params System.Linq.Expressions.Expression[])' has some invalid arguments
error CS1503: Argument 1: cannot convert from 'int' to 'System.Linq.Expressions.Expression'
error CS1503: Argument 2: cannot convert from 'int' to 'System.Linq.Expressions.Expression'
error CS1503: Argument 3: cannot convert from 'int' to 'System.Linq.Expressions.Expression'
error CS1503: Argument 4: cannot convert from 'int' to 'System.Linq.Expressions.Expression'
error CS1503: Argument 5: cannot convert from 'int' to 'System.Linq.Expressions.Expression'
Is there an undocumented limitation to the number of parameters?
:edit
Thanks to the answer of an unknown author that deleted its answer 10 seconds later i see that LinqKit is compiled with .NET 3.5 whereas this caused the limitation of System.Func<> to 4 parameters.
:edit2
The suggested Compile().Invoke()
workaround is not working in all cases in connection with queries (which i need). Thus i created a fork from the LINQKit project and added some code to support up to 16 parameters:
https://github.com/ViRuSTriNiTy/LINQKit/commit/bcca71978ef3fbb988d242463adfbc4e9cd42565
Upvotes: 2
Views: 1670
Reputation: 152566
When you add a fifth parameter, you're binding to a different Invoke
that the one in LinqKit
:
public static TResult Invoke<T1, T2, T3, T4, TResult> (
this Expression<Func<T1, T2, T3, T4, TResult>> expr, T1 arg1, T2 arg2, T3 arg3, T4 arg4)
{
return expr.Compile ().Invoke (arg1, arg2, arg3, arg4);
}
Note that there's not one with 5 arguments, so you end up binding to Expression.Invoke
, which takes a parameter array of Expression
s:
public static InvocationExpression Invoke(Expression expression, params Expression[] arguments) {
return Invoke(expression, (IEnumerable<Expression>)arguments);
}
Luckily, you can replicate the implementation from LinqKit by just calling Compile()
on the expression to turn it into a delegate:
public class ExpressionTester
{
public ExpressionTester()
{
Expressions.DoSomething.Compile().Invoke(1, 2, 3, 4, 5);
}
}
Upvotes: 4
Reputation: 24395
You could just call .Compile().Invoke()
instead. This code compiles:
public class Expressions
{
public static System.Linq.Expressions.Expression<
System.Func<int, int, int, int, int, bool>>
DoSomething =
(a, b, c, d, e) => false;
}
public class ExpressionTester
{
public ExpressionTester()
{
Expressions.DoSomething.Compile().Invoke(1, 2, 3, 4, 5);
}
}
Upvotes: 2
Reputation: 111860
The LinqKit 1.1.2 I've found on nuget (and on github) supports up to four parameters for the Invoke
...
public static TResult Invoke<T1, T2, T3, T4, TResult>(this Expression<Func<T1, T2, T3, T4, TResult>> expr, T1 arg1, T2 arg2, T3 arg3, T4 arg4)
{
return expr.Compile()(arg1, arg2, arg3, arg4);
}
It is trivial to do it for 5 parameters based on the one with 4.
public static TResult Invoke<T1, T2, T3, T4, T5, TResult>(this Expression<Func<T1, T2, T3, T4, T5, TResult>> expr, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5)
{
return expr.Compile()(arg1, arg2, arg3, arg4, arg5);
}
Upvotes: 3