将类型动态传递给通用模板

本文关键字:类型 动态 | 更新日期: 2023-09-27 18:21:16

我在C#中遇到了一个反射问题。我需要构造一个通用方法,用反射动态实例化类类型。我尝试的是以下内容。

Type myClass = Type.GetType(deviceBehavior.@class);
Type myInterfaceClass = myClass.GetInterface(deviceBehavior.@interface);
if (typeof (AnotherInterface).IsAssignableFrom(interfaceClass))
{
    CreateManager<interfaceClass>(serviceProvider, deviceCapability);
}

我的CreateManager方法如下:

private void CreateManager<T>(ServiceProvider serviceProvider, DeviceCapability deviceCapability)
{
    T instanceToCreate = CreateClass<T>(serviceProvider, deviceCapability);
    //Code to instantiate my class
}

问题是我打不到

CreateManager(serviceProvider,deviceCapability);

如何将接口传递给泛型类型?我搜索了一下,找不到任何我能清楚理解的东西。即

对泛型类型参数调用静态方法

传递实例化的System.Type作为泛型类的类型参数

将类型动态传递给通用模板

假设CreateManager<T>是类型为Foo:的方法

public class Foo
{
    private void CreateManager<T>(ServiceProvider serviceProvider,
                                  DeviceCapability deviceCapability)
    {
    }
}

为了动态调用泛型方法,您需要首先获得MethodInfo,然后使用要传递的实际类型调用MakeGenericMethod(我选择string作为示例)

var foo = new Foo();
var createManagerMethod = foo.GetType()
                             .GetMethod("CreateManager", 
                                         BindingFlags.Instance | BindingFlags.NonPublic);
var method = createManagerMethod.MakeGenericMethod(typeof(string));
method.Invoke(foo, new object[] { new ServiceProvider(), new DeviceCapability() });

最后,使用适当的对象实例和参数调用Invoke

我不明白你为什么需要反思。你可以像下面的一样做

public interface IYourInterface //Give it a good name
{
    void Instantiate(ServiceProvider serviceProvider, DeviceCapability deviceCapability);
}
public class YourClass : IYourInterface
{
    public YourClass() 
    {
        // do something if you want
    }
    public void Instantiate (ServiceProvider serviceProvider, DeviceCapability deviceCapability)
    {
       // what ever needs to be done here
    }
}
private void CreateManager<T>(ServiceProvider serviceProvider, DeviceCapability deviceCapability) 
    where T : IYourInterface, new()
{
    var instance = new T();
    instance.Instantiate(serviceProvider, deviceCapability);
}
/*
   Usage
*/
    CreateManager<YourClass>(serviceProvider, deviceCapability);