2010-02-11 19 views
48

Mam klasę abstrakcyjną i chcę ją zinicjalizować dla klasy, która ją rozszerza.C# instantiate klasa ze stringa

Mam nazwę klasy podrzędnej jako ciąg znaków.

Poza tym ...

String childClassString; 
MyAbstractClass myObject; 

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

Jak mogę to zrobić? Zasadniczo jak mogę pozbyć się tutaj instrukcji if?

+1

Dlaczego trzeba instanciate swoją klasę z ciągiem? W zależności od Twojego przypadku, mogą pojawić się "czystsze" rozwiązania, szczególnie jeśli nie chcesz używać refleksji. –

+1

@SylvestreEquy, ale może w czyichś sprawach, to tylko rozwiązanie ... Pytania na SO nie służą tylko tym, którzy ich proszą. –

Odpowiedz

90

Spójrz na Activator.CreateInstance().

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

lub

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

Pracował jak urok. Jeśli ktoś ma problemy z uzyskaniem w pełni kwalifikowanej nazwy, ten fragment kodu jest pomocny "string typex = typeof (classname) .AssemblyQualifiedName; –

+0

Mimo że w dokumentacji 'GetType' dla parametru' typeName' jest napisane "Nazwa kwalifikowana do zestawu typu", w rzeczywistości nie trzeba podawać nazwy zespołu. Jeśli typ znajduje się w zestawie wywołującym, wystarczy nazwa typu kwalifikowanego obszaru nazw. –

18

Wierzę, że to powinno działać:

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

null w pierwszych domyślnych parametrów do bieżącego wykonującego montaż. Aby uzyskać więcej odniesienia: MSDN

edit: zapomniałem oddać do MyAbstractClass

1

miałem pewne trudności wykonawczych niektóre odpowiedzi tutaj, ponieważ starałem się instancję obiektu z innego zespołu (ale w tym samym roztworze). Pomyślałem więc, że opublikuję to, co znalazłem.

Po pierwsze, metoda Activator.CreateInstance ma kilka przeciążeń. Po prostu zadzwoń pod numer Activator.CreateInstance(Type.GetType("MyObj")), który zakłada, że ​​obiekt jest zdefiniowany w bieżącym złożeniu i zwraca wartość MyObj.

Jeśli nazywasz to zalecanym w odpowiedzi tutaj: Activator.CreateInstance(string AssemblyName, string FullyQualifiedObjectName), to zamiast tego zwraca ObjectHandle, i musisz wywołać Unwrap() na nim, aby uzyskać swój obiekt. To przeciążenie jest przydatne przy próbie wywołania metody zdefiniowanej w innym zestawie (BTW, można użyć tego przeciążenia w bieżącym złożeniu, po prostu pozostaw parametr null wartością AssemblyName).

Teraz odkryłem, że powyższa sugestia, aby użyć typeof(ParentNamespace.ChildNamespace.MyObject).AssemblyQualifiedName dla AssemblyName faktycznie dała mi błędy, i nie mogłem tego zrobić. Dostałbym System.IO.FileLoadException (nie można załadować pliku lub zespołu ...).

Co mogę dostać się do pracy jest następujący:

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