2010-02-11 3 views
48

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

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

Кроме этого ...

String childClassString; 
MyAbstractClass myObject; 

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

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

+1

Почему вам нужно создать экземпляр вашего класса с помощью строки? В зависимости от вашего случая могут быть «более чистые» решения, особенно если вы не отказываетесь от использования рефлексии. –

+1

@SylvestreEquy, но, возможно, в чьих-то проблемах, это просто решение ... Вопросы на SO не только обслуживают тех, кто их спрашивает. –

ответ

90

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

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

или

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

Работал как шарм. В случае, если у кого-то есть проблемы с получением полного имени, этот фрагмент кода полезен 'string typex = typeof (имя класса) .AssemblyQualifiedName; –

+0

Несмотря на то, что в документации 'GetType' для параметра' typeName' указано «Имя типа, имеющее сборку», вам фактически не нужно включать имя сборки. Если тип находится в вызывающей сборке, достаточно только имя типа с именем пространства. –

18

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

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

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

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

1

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

Во-первых, метод 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(); 
Смежные вопросы