Reputation: 19586
I am dynamically creating a Lambda expression (based on user input but at the moment using dummy values for a proof-of-concept) for a type which I will only know at runtime. I therefore need to pass the T
portion of the Func<T,TResult>
as a dynamic type, since I won't know the type until runtime (TResult
will always be a bool
).
It seems that I cannot pass in a Type
variable or use typeof
with generics. Basically I'm trying to do something like this:
// (f => f.Baz == 1)
Type theType = Type.GetType("Foo");
ParameterExpression pe = Expression.Parameter(theType, "f");
Expression left = Expression.Property(pe, theType.GetProperty("Baz"));
Expression right = Expression.Constant(1);
Expression expr = Expression.Equal(left, right);
// This works fine but uses a hard-coded type, which I won't know until runtime:
// var lambda = Expression.Lambda<Func<Foo,bool>>(expr, new ParameterExpression[] { pe }).Compile();
var lambda = Expression.Lambda<Func<theType, bool>>(expr, new ParameterExpression[] { pe }).Compile();
However, I cannot use the variable theType
as the T
portion of the Func. How can I fix this?
Upvotes: 0
Views: 351
Reputation: 111840
No you can't.
For example, in C#, you can't:
Type t = typeof(int);
List<t> list = new List<t>();
or
object list = new List<t>();
Unless you use reflection, but then you have to put the list in an object
, and you can use it only through reflection.
So if you want you can save your Func<>
in an object
(or a dynamic
) but nothing more.
What you COULD do is always return Func<object, bool>
and cast the object to the desidered type IN the lambda function (so use a Expression.Convert(pe, theType)
);
Or you could use the dynamic:
// lambda == Func<Foo, bool>
dynamic lamdba = Expression.Lambda(expr, new ParameterExpression[] { pe }).Compile();
bool res = lambda(myvalue);
or
// lambda == Func<Foo, bool>
Delegate lamdba = Expression.Lambda(expr, new ParameterExpression[] { pe }).Compile();
bool res = (bool)lambda2.DynamicInvoke(t);
To be taken "not as real" some benchmarks (in StopWatch.Ticks, look at them only for proportions) (Release Mode + Start Without Debugging + some useless cycles so that they are "hot"):
236384685 dynamic
56773593 Func<object, bool> + cast
10556024247 DynamicInvoke
as a note, Func<Foo, bool>
has the same speed, so there isn't any speed lost in the extra cast.
You can see the code here http://ideone.com/qhnVP3
Upvotes: 1