Create delegate from constructor
As phoog points out a constructor doesn't "return" a value; plus you get information about it with ConstructorInfo
and not MethodInfo
; which means you can't create a delegate around it directly. You have to create code that invokes the constructor and returns the value. For example:
var ctor = type.GetConstructor(Type.EmptyTypes);
if (ctor == null) throw new MissingMethodException("There is no constructor without defined parameters for this object");
DynamicMethod dynamic = new DynamicMethod(string.Empty,
type,
Type.EmptyTypes,
type);
ILGenerator il = dynamic.GetILGenerator();
il.DeclareLocal(type);
il.Emit(OpCodes.Newobj, ctor);
il.Emit(OpCodes.Stloc_0);
il.Emit(OpCodes.Ldloc_0);
il.Emit(OpCodes.Ret);
var func = (Func<object>)dynamic.CreateDelegate(typeof(Func<object>));
Of course, if you don't know the type at compile time then you can only deal with Object
...
Try it:
Dictionary<Type, Delegate> cache = new Dictionary<Type, Delegate>();
public T Create<T>()
{
if (!cache.TryGetValue(typeof(T), out var d))
d = cache[typeof(T)]
= Expression.Lambda<Func<T>>(
Expression.New(typeof(T)),
Array.Empty<ParameterExpression>())
.Compile();
return ((Func<T>)d)();
}
Reflection is very slow! Speed tests are here (in Russian): https://ru.stackoverflow.com/a/860921/218063
It would not be very useful to have a delegate that points to a constructor, since constructors do not have a return value. The delegate would construct an object but give you no way of retaining a reference to it.
You can of course create delegates that return the newly-constructed object:
Func<object> theDelegate = () => new object();
You could also create a delegate from the Invoke()
method of the constructor's ConstructorInfo
For other types of objects:
Func<string> theDelegate = () => new string('w', 3);
Func<SomeClassInMyProject> theDelegate = () => new SomeClassInMyProject();
The last line assumes there's an accessible parameterless constructor.
Update with CreateDelegate()
T CallConstructor<T>() where T : new() { return new T(); }
Delegate MakeTheDelegate(Type t)
{
MethodInfo generic = //use your favorite technique to get the MethodInfo for the CallConstructor method
MethodInfo constructed = generic.MakeGenericMethod(t);
Type delType = typeof(Func<>).MakeGenericType(t);
return constructed.CreateDelegate(delType);
}