Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Making a compiled constructor expression with just the Type of the type

I've been playing around, partially reinventing wheels so that I can understand how proper wheels spin round.

Consider this generic function for compiling and returning the default constructor of a type.

public static Func<TConcrete> Creator<TConcrete>()
{
    // All checking removed for brevity
    var ctor = typeof(TConcrete).GetConstructor(new Type[0]);
    var lambda = Expression.Lambda<Func<TConcrete>>(Expression.New(ctor));
    return lambda.Compile();
}

I believe this will return me a nice typed delegate that I can use to instantiate the passed type.

Now consider, I want a function that would do this for a set of different types, how would I go about that? I was thiking along the lines of ...

public static IEnumerable<Delegate> Creators(IEnumerable<Type> types)
{
    foreach (var type in types)
    {
        var ctor = type.GetConstructor(new Type[0]);
        var lamda = Expression.Lambda<Func<????>>(Expression.New(ctor));
        yield return lambda.Compile();
    }
}

As you can see from the ???? this is where I got stuck. Is there a way to do this or is my approach just flawed?

like image 350
Jodrell Avatar asked Jun 21 '12 16:06

Jodrell


2 Answers

You can use a different Expression.Lambda call which takes the delegate type as a Type:

Type delegateType = typeof(Func<>).MakeGenericType(type);
var lambda = Expression.Lambda(delegateType, Expression.New(ctor));
yield return lambda.Compile();

Note that this overload of Lambda returns the non-generic LambdaExpression type rather than Expression<TDelegate> - but it still exposes a Compile method which returns Delegate, which is all you need here. Basically it's just avoiding some of the compile-time type checking you benefit from in your "known delegate type" code.

like image 153
Jon Skeet Avatar answered Oct 28 '22 20:10

Jon Skeet


Use the non-generic overload in combination with MakeGenericType:

var lamda = Expression.Lambda<Func<????>>(Expression.New(ctor));

Should become:

var funcType = typeof(Func<>).MakeGenericType(type);
var lamda = Expression.Lambda(funcType, Expression.New(ctor));
like image 26
Kirk Woll Avatar answered Oct 28 '22 21:10

Kirk Woll