1

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?

nawfal
  • 70,104
  • 56
  • 326
  • 368

2 Answers2

6

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.

Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
  • Eric, thanks for your answer that I am not doing anything useful (which makes sense). I just started to explore Expressions, where I started to implement many of my old code (not for production stuff) the *expression way* and this was more an exercise than anything. – nawfal Apr 23 '13 at 17:18
2

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...)

nawfal
  • 70,104
  • 56
  • 326
  • 368
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194