Как создать экземпляр класса с заданным именем строки? - PullRequest
62 голосов
/ 11 февраля 2010

У меня есть абстрактный класс, и я хочу инициализировать его для класса, расширяющего его.

У меня есть имя дочерних классов в виде строки.

Помимо этого ...

String childClassString;
MyAbstractClass myObject;

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

Как я могу это сделать? В основном, как мне избавиться от операторов if здесь?

Ответы [ 3 ]

111 голосов
/ 11 февраля 2010

Посмотрите на Activator.CreateInstance ().

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

или

var type = Type.GetType("MyFullyQualifiedTypeName");
var myObject = (MyAbstractClass)Activator.CreateInstance(type);
20 голосов
/ 11 февраля 2010

Я считаю, что это должно работать:

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

null в первом параметре по умолчанию соответствует текущей исполняющей сборке. Для получения дополнительной информации: MSDN

редактировать: забыл привести к MyAbstractClass

5 голосов
/ 03 апреля 2017

Мне было сложно реализовать некоторые ответы здесь, потому что я пытался создать экземпляр объекта из другой сборки (но в том же решении). Поэтому я решил опубликовать то, что нашел для работы.

Во-первых, метод Activator.CreateInstance имеет несколько перегрузок. Если вы просто вызываете Activator.CreateInstance(Type.GetType("MyObj")), это предполагает, что объект определен в текущей сборке, и возвращает MyObj.

Если вы называете его как рекомендовано в ответах здесь: Activator.CreateInstance(string AssemblyName, string FullyQualifiedObjectName), то вместо этого он возвращает ObjectHandle, и вам нужно вызвать Unwrap() для него, чтобы получить ваш объект. Эта перегрузка полезна при попытке вызвать метод, определенный в другой сборке (кстати, вы можете использовать эту перегрузку в текущей сборке, просто оставьте параметр AssemblyName пустым).

Теперь я обнаружил, что предложенное выше использование typeof(ParentNamespace.ChildNamespace.MyObject).AssemblyQualifiedName для AssemblyName на самом деле дало мне ошибки, и я не мог заставить это работать. Я бы получил System.IO.FileLoadException (не удалось загрузить файл или сборку ...).

Что я получил на работу, так это:

var container = Activator.CreateInstance(@"AssemblyName",@"ParentNamespace.ChildNamespace.MyObject");
MyObject obj = (MyObject)container.Unwrap();
obj.DoStuff();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...