Reputation: 73183
I have this static function
public static object Create(Type t)
{
//unimportant
}
I don't have control on the above function above, so I cant alter it. The problem is it's not generic, so I have to cast the returned object to some type. This type is provided by the constraint of another generic class from where I call the Create
method.
This is where I have reached:
public static class Creator<T>
{
public static void Create()
{
var m = typeof(SomeClass).GetMethod("Create");
var p = Expression.Parameter(typeof(Type));
var e = Expression.Call(m, p);
//at this stage I want to create delegate for calling the 'Create' method,
//then pass typeof(T) as parameter, get returned object,
//and finally cast it to 'T'.
//for eg, I can do it like this:
var f = Expression.Lambda<Func<Type, object>>(e, p).Compile();
Func<T> mainThing = () => (T)f(typeof(T));
//is there a way I can achieve in one step?
}
}
In my above approach I'm not compiling the final delegate but one step previously. How do I incorporate the cast too before compilation and get Func<T>
back?
Upvotes: 1
Views: 1571
Reputation: 1500535
I think you just need a call to Expression.Convert
, and use a ConstantExpression
instead of a ParameterExpression
:
var method = typeof(SomeClass).GetMethod("Create");
var call = Expression.Call(method, Expression.Constant(typeof(T), typeof(Type)));
var conversion = Expression.Convert(call, typeof(T));
var function = Expression.Lambda<Func<T>>(conversion).Compile();
(I haven't tested it, but it looks okay...)
Upvotes: 2
Reputation: 660088
You seem to be jumping through a lot of unnecessary hoops. I don't understand why you're doing this through an expression tree. Why not just:
public static class Creator<T>
{
public static void Create()
{
Func<T> mainThing = () => (T)SomeClass.Create(typeof(T));
}
}
???
What's the purpose of creating an expression tree of a method call only to turn it back into a delegate that makes a method call which you then call? Why not just call SomeClass.Create
directly?
Is there something I'm missing here?
To answer your actual question:
How do I incorporate the cast too before compilation?
Use Expression.Convert()
to create an expression tree node that represents a conversion.
Upvotes: 6