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?
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.
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));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With