给定其字符串名称,如何实例化一个类?


71

我有一个抽象类,我想将其初始化为扩展它的类。

我有子类名称作为字符串。

除此之外...

String childClassString;
MyAbstractClass myObject;

if (childClassString = "myExtenedObjectA")
    myObject = new ExtenedObjectA();
if (childClassString = "myExtenedObjectB")
    myObject = new ExtenedObjectB();

我怎样才能做到这一点?基本上,我该如何摆脱if语句?

Answers:


126

查看Activator.CreateInstance()。

myObject = (MyAbstractClass)Activator.CreateInstance("AssemblyName", "TypeName");

要么

var type = Type.GetType("MyFullyQualifiedTypeName");
var myObject = (MyAbstractClass)Activator.CreateInstance(type);

7
像魅力一样工作。如果有人在获取标准名称时遇到问题,则这段代码很有帮助'string typex = typeof(classname).AssemblyQualifiedName;。
Sanjit Misra

即使GetTypetypeName参数的文档说“类型的程序集限定名称”,您实际上也不需要包括程序集名称。如果类型在调用程序集中,则仅名称空间限定的类型名称就足够了。
爱德华·布雷

21

我相信这应该有效:

myObject = (MyAbstractClass)Activator.CreateInstance(null, childClassString);

null一个参数中的in默认为当前执行的程序集。有关更多参考:MSDN

编辑:忘记投射到 MyAbstractClass


5

我在这里实现一些答案有些困难,因为我试图从不同的程序集中实例化一个对象(但在同一解决方案中)。所以我想我会发布我发现有用的东西。

首先,该Activator.CreateInstance方法有多个重载。如果仅调用Activator.CreateInstance(Type.GetType("MyObj")),则假定该对象已在当前程序集中定义,并且返回MyObj

如果按照此处的答案中的建议进行调用Activator.CreateInstance(string AssemblyName, string FullyQualifiedObjectName),则它返回ObjectHandle,而您需要对其进行调用Unwrap()以获取您的对象。当尝试调用在不同程序集中定义的方法时,此重载很有用(顺便说一句,您可以在当前程序集中使用此重载,只需将AssemblyName参数保留为null)。

现在,我发现上面使用的建议typeof(ParentNamespace.ChildNamespace.MyObject).AssemblyQualifiedName 进行AssemblyName居然给我的错误,我不能得到那个工作。我会得到System.IO.FileLoadException(无法加载文件或程序集...)。

我所做的工作如下:

var container = Activator.CreateInstance(@"AssemblyName",@"ParentNamespace.ChildNamespace.MyObject");
MyObject obj = (MyObject)container.Unwrap();
obj.DoStuff();
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.