С# экземпляр класса из строки
У меня есть абстрактный класс, и я хочу инициализировать его для класса, который расширяет его.
У меня есть имя дочерних классов в виде строки.
Кроме того...
String childClassString;
MyAbstractClass myObject;
if (childClassString = "myExtenedObjectA")
myObject = new ExtenedObjectA();
if (childClassString = "myExtenedObjectB")
myObject = new ExtenedObjectB();
Как я могу это сделать? В основном, как я могу избавиться от операторов if здесь?
Ответы
Ответ 1
Посмотрите на Activator.CreateInstance().
myObject = (MyAbstractClass)Activator.CreateInstance("AssemblyName", "TypeName");
или
var type = Type.GetType("MyFullyQualifiedTypeName");
var myObject = (MyAbstractClass)Activator.CreateInstance(type);
Ответ 2
Я считаю, что это должно работать:
myObject = (MyAbstractClass)Activator.CreateInstance(null, childClassString);
null
в первом параметре по умолчанию используется текущая исполняющая сборка. Для получения дополнительной информации: MSDN
edit: забыли перевести на MyAbstractClass
Ответ 3
Мне было сложно выполнить некоторые из ответов здесь, потому что я пытался создать экземпляр объекта из другой сборки (но в том же решении). Поэтому я думал, что опубликую то, что нашел, чтобы работать.
Во-первых, метод Activator.CreateInstance
имеет несколько перегрузок. Если вы просто вызываете Activator.CreateInstance(Type.GetType("MyObj"))
, это предполагает, что объект определен в текущей сборке, и он возвращает MyObj
.
Если вы ответите так, как указано в ответах здесь: Activator.CreateInstance(string AssemblyName, string FullyQualifiedObjectName)
, вместо этого он возвращает ObjectHandle
, и вам нужно вызвать Unwrap()
на нем, чтобы получить ваш объект. Эта перегрузка полезна при попытке вызова метода, определенного в другой сборке (BTW, вы можете использовать эту перегрузку в текущей сборке, просто оставьте параметр 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();