86

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?

Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
ctrlShiftBryan
  • 27,092
  • 26
  • 73
  • 78
  • Does this answer your question? [Create an instance of a class from a string](https://stackoverflow.com/questions/223952/create-an-instance-of-a-class-from-a-string) – GSerg May 25 '21 at 17:03

3 Answers3

141

Look at Activator.CreateInstance().

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

or

var type = Type.GetType("MyFullyQualifiedTypeName");
var myObject = (MyAbstractClass)Activator.CreateInstance(type);
Seth Petry-Johnson
  • 11,845
  • 7
  • 49
  • 69
  • 9
    Worked like a charm. In case anybody has problems getting the fully qualified name, this piece of code is helpful ' string typex = typeof(classname).AssemblyQualifiedName; – Sanjit Misra Jun 21 '13 at 10:50
  • 2
    Even though the `GetType` documentation for its `typeName` parameter says "The assembly-qualified name of the type", you don't actually need to include the assembly name. If the type is in the calling assembly, just the namespace-qualified type name is sufficient. – Edward Brey May 22 '15 at 15:43
24

I believe this should work:

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

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

edit: forgot to cast to MyAbstractClass

Community
  • 1
  • 1
IAbstract
  • 19,551
  • 15
  • 98
  • 146
10

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.CreateInstance method 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.

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 AssemblyName parameter null).

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

What I did get to work is as follows:

var container = Activator.CreateInstance(@"AssemblyName",@"ParentNamespace.ChildNamespace.MyObject");
MyObject obj = (MyObject)container.Unwrap();
obj.DoStuff();
Kevin Fichter
  • 1,067
  • 1
  • 11
  • 17