如何使用Activator创建泛型类型的实例并将其转换回该类型?

Baz*_*zzz 36 c# generics reflection activator

我有一个泛型类型Store<T>,用于Activator创建这种类型的实例.现在,在使用Activator之后,我可以将结果对象的类型转换object回实例化类型吗?我知道我用来实例化泛型的类型.请参阅以下代码:

class Store<T> where T : IStorable 
{}

class Beer : IStorable 
{}

class BeerStore : Store<Beer>
{}

Type storeType = someObjectThatImplementsIStorable.GetType();
Type classType = typeof(Store<>);
Type[] typeParams = new Type[] { storeType };   
Type constructedType = classType.MakeGenericType(typeParams);

object x = Activator.CreateInstance(constructedType, new object[] { someParameter });
Run Code Online (Sandbox Code Playgroud)

我想做的是这样的事情:

var store = (Store<typeof(objectThatImplementsIStorable)>)x;
Run Code Online (Sandbox Code Playgroud)

但由于显而易见的原因,这不起作用.作为替代方案,我试过:

var store = (Store<IStorable>)x;
Run Code Online (Sandbox Code Playgroud)

这可能在我看来有效,但给出了一个InvalidCastException.

如何再次访问Store<T>对象中我知道的方法x

das*_*ght 30

由于实际类型T仅通过反射可用,因此您还需要访问Store<T>反射方法:

Type constructedType = classType.MakeGenericType(typeParams);

object x = Activator.CreateInstance(constructedType, new object[] { someParameter });
var method = constructedType.GetMethod("MyMethodTakingT");
var res = method.Invoke(x, new object[] {someObjectThatImplementsStorable});
Run Code Online (Sandbox Code Playgroud)

编辑您还可以定义一个IStore不使用泛型的附加接口,而是使用IStorable:

interface IStore {
    int CountItems(IStorable item);
}
class Store<T> : IStore where T : IStorable {
    int CountItems(IStorable item) {
        return count;
    }
}
Run Code Online (Sandbox Code Playgroud)

Store<T>将保持通用,但您可以CountItems通过转换来访问它IStore:

var x = (IStore)Activator.CreateInstance(constructedType, new object[] { someParameter });
var count = x.CountItems((IStorable)someObjectThatImplementsStorable);
Run Code Online (Sandbox Code Playgroud)


Not*_*ple 6

你不能把它包起来吗?

就像是

public Store<T> IConstructStore<T>(T item) where T : IStorable 
{
 return Activator.CreateInstance(typeof(Store<T>), new object[] { someParameter }) as Store<T>;
}
Run Code Online (Sandbox Code Playgroud)

或者我错过了你想要做什么?

IE

class Program
{
    static void Main(string[] args)
    {
        Beer b = new Beer();
        var beerStore = IConstructStore(b);
        Console.WriteLine(beerStore.test);
        Console.WriteLine(beerStore.GetType().ToString());
    }

    public static Store<T> IConstructStore<T>(T item) where T : IStorable
    {
        return Activator.CreateInstance(typeof(Store<T>), new object[] { }) as Store<T>;
    }
}

interface IStorable { }

class Store<T> where T : IStorable
{
    public int test = 1;
}

class Beer : IStorable
{ }
Run Code Online (Sandbox Code Playgroud)

印刷

1 
ConsoleApp1.Store'1[ConsoleApp1.Beer]
Run Code Online (Sandbox Code Playgroud)