2010-02-11 17 views
48

Ho una classe astratta e voglio inizializzarla in una classe che la estende.C# classe instantiate dalla stringa

Ho il nome delle classi figlio come una stringa.

Oltre a questo ...

String childClassString; 
MyAbstractClass myObject; 

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

Come posso fare questo? Fondamentalmente come faccio a sbarazzarmi delle dichiarazioni if ​​qui?

+1

Perché è necessario instanciate la classe con una corda? A seconda del caso, potrebbero esserci soluzioni "più pulite", soprattutto se non si è riluttanti all'utilizzo del riflesso. –

+1

@SylvestreEquy ma forse nei casi di qualcun'altro, questa è solo la soluzione ... Le domande su SO non servono solo a chi le chiede. –

risposta

90

Vedere Activator.CreateInstance().

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

o

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

Ha funzionato come un fascino. Nel caso qualcuno abbia problemi ad ottenere il nome completo, questa parte di codice è utile 'string typex = typeof (nomeclass) .AssemblyQualifiedName; –

+0

Anche se la documentazione 'GetType' per il suo parametro' typeName' dice "Il nome qualificato dell'assemblaggio del tipo", in realtà non è necessario includere il nome dell'assembly. Se il tipo si trova nell'assieme di chiamata, è sufficiente il nome del tipo qualificato per lo spazio dei nomi. –

18

Credo che questo dovrebbe funzionare:

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

Il null nel primo parametro di default per l'assemblaggio in esecuzione corrente. Per maggiori riferimento: MSDN

edit: ha dimenticato di lanciare a MyAbstractClass

1

Ho avuto qualche difficoltà l'attuazione di alcune delle risposte qui perché stavo cercando di un'istanza di un oggetto da un assembly diverso (ma nella stessa soluzione). Così ho pensato di pubblicare ciò che trovavo al lavoro.

Innanzitutto, il metodo Activator.CreateInstance ha diversi sovraccarichi. Se si chiama semplicemente Activator.CreateInstance(Type.GetType("MyObj")), si presuppone che l'oggetto sia definito nell'assieme corrente e restituisce un valore MyObj.

Se lo si chiama come raccomandato nelle risposte qui: Activator.CreateInstance(string AssemblyName, string FullyQualifiedObjectName), allora invece restituisce un ObjectHandle, ed è necessario chiamare Unwrap() su di esso per ottenere il vostro oggetto. Questo sovraccarico è utile quando si tenta di chiamare un metodo definito in un assembly diverso (BTW, è possibile utilizzare questo overload nell'assieme corrente, lasciare il parametro AssemblyName null).

Ora, ho trovato che il suggerimento di cui sopra per utilizzare typeof(ParentNamespace.ChildNamespace.MyObject).AssemblyQualifiedName per AssemblyName in realtà mi ha dato errori, e non ho potuto farlo funzionare. Otterrei System.IO.FileLoadException (impossibile caricare file o assembly ...).

Quello che ho fatto andare al lavoro è la seguente:

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