C# 如何使用 Activator 创建泛型类型的实例并将其转换回该类型?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9140873/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to use Activator to create an instance of a generic Type and casting it back to that type?
提问by Bazzz
I have a generic type Store<T>and use Activatorto make an instance of this type. Now how, after using the Activator, can I cast the resulted object of type objectback to the instantiated type? I know the type that I used to instantiate the generic. Please see the following code:
我有一个泛型类型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 });
What I would like to do is something like this:
我想做的是这样的:
var store = (Store<typeof(objectThatImplementsIStorable)>)x;
but that doesn't work for obvious reasons. As an alternative I tried:
但由于显而易见的原因,这不起作用。作为替代,我尝试过:
var store = (Store<IStorable>)x;
which could possibly work in my opinion, but gives an InvalidCastException.
这在我看来可能有效,但给出了InvalidCastException.
How do I get access again to the Store<T>methods that I know are in the object x?
如何再次访问Store<T>我知道在对象中的方法x?
采纳答案by dasblinkenlight
Since the actual type Tis available to you only through reflection, you would need to access methods of Store<T>through reflection as well:
由于实际类型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});
EDITYou could also define an additional IStoreinterface that does not use generics, and uses IStorableinstead:
编辑您还可以定义一个IStore不使用泛型的附加接口,而是使用IStorable:
interface IStore {
int CountItems(IStorable item);
}
class Store<T> : IStore where T : IStorable {
int CountItems(IStorable item) {
return count;
}
}
Your Store<T>would remain generic, but you would get access to its CountItemsby casting to IStore:
您Store<T>将保持通用,但您可以CountItems通过强制转换来访问它IStore:
var x = (IStore)Activator.CreateInstance(constructedType, new object[] { someParameter });
var count = x.CountItems((IStorable)someObjectThatImplementsStorable);
回答by Not loved
Cant you just wrap it?
你不能把它包起来吗?
something like
就像是
public Store<T> IConstructStore<T>(T item) where T : IStorable
{
return Activator.CreateInstance(typeof(Store<T>), new object[] { someParameter }) as Store<T>;
}
or am i missing what you are trying to do?
或者我错过了你想要做什么?
IE
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
{ }
prints
印刷
1
ConsoleApp1.Store'1[ConsoleApp1.Beer]
回答by Snowbear
Most appropriate answer in my opinion would be 'you can't do it in this way'.
在我看来,最合适的答案是“你不能这样做”。
You might try introducing an interface IStorageand try making it covariant or contravariant (have you seen that option?). If it is not an option, for example if you have both input and output generic types used in Storage, then there is no way to implement what you want. The reason is that Storage<Beer>cannot be safely used as Storage<IStorable>due to this case:
您可能会尝试引入一个接口IStorage并尝试使其成为协变或逆变(您见过那个选项吗?)。如果它不是一个选项,例如,如果您在 中同时使用了输入和输出泛型类型Storage,则无法实现您想要的。原因是由于这种情况Storage<Beer>不能安全使用Storage<IStorable>:
Storage<IStorable> store = new Storage<Beer>(); // let's pretend we can do it
store.Save(new StorableButNotBeer()); // what will happen here?
The only possible workaround for you as I see is to move casting out from this method and cast the object in the place where you know all the exact types:
正如我所见,对您来说唯一可能的解决方法是从此方法中移出并将对象投射到您知道所有确切类型的位置:
public void object CreateStore(Type istorableType)
{
// here is your activator code, but you will have to return an object
}
var beerStore = (Store<Beer>)CreateStore(typeof(Beer));
回答by Uri
Let's say that someObjectThatImplementsIStorable is of type MyStorable.
假设 someObjectThatImplementsIStorable 是 MyStorable 类型。
e.g. MyStorable someObjectThatImplementsIStorable = new MyStorable( ); ... // rest of your code here.
例如 MyStorable someObjectThatImplementsIStorable = new MyStorable( ); ... // 其余代码在这里。
Then x cannot be cast to Store, but it can be cast to Store. The following will work: (Store)x
那么 x 不能被强制转换为 Store,但它可以被强制转换为 Store。以下将起作用:(商店)x
Note that although MyStorable implements IStorable, there is no relationship between Store and Store. These are two distinct classes that do not derive from each other.
注意,虽然 MyStorable 实现了 IStorable,但是 Store 和 Store 之间没有关系。这是两个不同的类,它们不是相互派生的。
u.
你。
回答by Darío Andrés Mu?oz Prudant
T must be the type Store avoiding the use of typeof(Store
T 必须是类型 Store 避免使用 typeof(Store

