C# 如何实例化一个给定字符串名称的类?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2247598/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-07 00:45:40  来源:igfitidea点击:

How do I instantiate a class given its string name?

c#reflectionpolymorphism

提问by ctrlShiftBryan

I have an abstract class and I want to initalize it to a class that extends it.

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

I have the child classes name as a string.

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

Besides this...

除此以外...

String childClassString;
MyAbstractClass myObject;

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

How can I do this? Basically how do I get rid of the if statements here?

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

采纳答案by Seth Petry-Johnson

Look at Activator.CreateInstance().

看看 Activator.CreateInstance()。

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

or

或者

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

回答by IAbstract

I believe this should work:

我相信这应该有效:

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

The nullin the first parameter defaults to the current executing assembly. For more reference: MSDN

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

edit: forgot to cast to MyAbstractClass

编辑:忘了投 MyAbstractClass

回答by Kevin Fichter

I had some difficulty implementing some of the answers here because I was trying to instantiate an object from a different assembly (but in the same solution). So I thought I'd post what I found to work.

我在这里实现一些答案时遇到了一些困难,因为我试图从不同的程序集(但在相同的解决方案中)实例化一个对象。所以我想我会发布我发现的工作。

First, the Activator.CreateInstancemethod has several overloads. If you just call Activator.CreateInstance(Type.GetType("MyObj")), that assumes the object is defined in the current assembly, and it returns a MyObj.

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

If you call it as recommended in the answers here: Activator.CreateInstance(string AssemblyName, string FullyQualifiedObjectName), then it instead returns an ObjectHandle, and you need to call Unwrap()on it to get your object. This overload is useful when trying to call a method defined in a different assembly (BTW, you can use this overload in the current assembly, just leave the AssemblyNameparameter null).

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

Now, I found that the suggestion above to use typeof(ParentNamespace.ChildNamespace.MyObject).AssemblyQualifiedNamefor AssemblyNameactually gave me errors, and I could not get that to work. I'd get System.IO.FileLoadException(could not load file or assembly...).

现在,我发现上面使用typeof(ParentNamespace.ChildNamespace.MyObject).AssemblyQualifiedNamefor的建议AssemblyName实际上给了我错误,我无法让它起作用。我会得到System.IO.FileLoadException(无法加载文件或程序集...)。

What I did get to work is as follows:

我所做的工作如下:

var container = Activator.CreateInstance(@"AssemblyName",@"ParentNamespace.ChildNamespace.MyObject");
MyObject obj = (MyObject)container.Unwrap();
obj.DoStuff();