如何创建其构造函数需要委托函数参数的泛型类型的实例?

B.S*_*iuk 5 c# reflection generic-type-argument

我需要在其中使用以下通用类和方法ParseFrom()

public sealed class MessageParser<T> : MessageParser where T : IMessage<T>
{
    public MessageParser(Func<T> factory); //constructor
    public T ParseFrom(byte[] data);
}
Run Code Online (Sandbox Code Playgroud)

现在,我在编译时不知道这个类的参数类型,所以我使用类型反射和MakeGenericType()方法来做到这一点:

//Assuming itemInstance is given as input parameter 
Type typeArgument = itemInstance.GetType();
Type genericClass = typeof(MessageParser<>);
var genericType = genericClass.MakeGenericType(typeArgument);
var instance = Activator.CreateInstance(genericType);
Run Code Online (Sandbox Code Playgroud)

它给了我一个运行时错误: MessageParser<> 没有无参数构造函数。但是当我尝试Func<T> factory作为参数传递时CreateInstance()

var instance = Activator.CreateInstance(genericType, () => Activator.CreateInstance(typeArgument));
Run Code Online (Sandbox Code Playgroud)

它给了我一个编译错误:无法将 lambda 表达式转换为类型“字符串”,因为它不是委托类型。我在这里对委托函数使用了错误的语法吗?

Ser*_*rvy 5

动态构造未知类型的委托不像使用反射调用方法那么容易,因此最简单的选择是编写一个静态类型的方法来构造委托,然后使用反射调用它。

public class DelegateCreator
{
    public static Func<T> MakeConstructorStatically<T>()
    {
        return Activator.CreateInstance<T>;
    }

    public static object MakeConstructorDynamically(Type type)
    {
        return typeof(DelegateCreator)
            .GetMethod(nameof(MakeConstructorStatically))
            .MakeGenericMethod(type)
            .Invoke(null, Array.Empty<object>());
    }
}
Run Code Online (Sandbox Code Playgroud)