web-dev-qa-db-fra.com

Comment instancier une classe en fonction de son nom de chaîne?

J'ai une classe abstraite et je veux l'initier à une classe qui la prolonge.

J'ai le nom des classes enfants sous forme de chaîne.

Mis-à-part...

String childClassString;
MyAbstractClass myObject;

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

Comment puis-je faire ceci? Fondamentalement, comment puis-je me débarrasser des instructions if ici?

63
ctrlShiftBryan

Regardez Activator.CreateInstance ().

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

ou

var type = Type.GetType("MyFullyQualifiedTypeName");
var myObject = (MyAbstractClass)Activator.CreateInstance(type);
112
Seth Petry-Johnson

Je pense que cela devrait fonctionner:

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

Le null dans le premier paramètre est par défaut l'assembly en cours d'exécution. Pour plus de référence: MSDN

edit: oublié de caster en MyAbstractClass

20
IAbstract

J'ai eu quelques difficultés à mettre en œuvre certaines des réponses ici parce que j'essayais d'instancier un objet à partir d'un assembly différent (mais dans la même solution). J'ai donc pensé publier ce que j'ai trouvé efficace.

Premièrement, la méthode Activator.CreateInstance A plusieurs surcharges. Si vous appelez simplement Activator.CreateInstance(Type.GetType("MyObj")), cela suppose que l'objet est défini dans l'assembly en cours et renvoie un MyObj.

Si vous l'appelez comme recommandé dans les réponses ici: Activator.CreateInstance(string AssemblyName, string FullyQualifiedObjectName), alors il renvoie à la place un ObjectHandle, et vous devez appeler Unwrap() dessus pour obtenir votre objet. Cette surcharge est utile lorsque vous essayez d'appeler une méthode définie dans un assembly différent (BTW, vous pouvez utiliser cette surcharge dans l'assembly actuel, laissez simplement le paramètre AssemblyName null).

Maintenant, j'ai trouvé que la suggestion ci-dessus d'utiliser typeof(ParentNamespace.ChildNamespace.MyObject).AssemblyQualifiedName pour AssemblyName m'a en fait donné des erreurs, et je n'ai pas pu faire fonctionner cela. J'obtiendrais System.IO.FileLoadException (Impossible de charger le fichier ou l'assemblage ...).

Ce que je suis arrivé au travail est le suivant:

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