web-dev-qa-db-fra.com

Créer une instance d'une classe à partir d'une chaîne

Y at-il un moyen de créer une instance d'une classe basée sur le fait que je connais le nom de la classe au moment de l'exécution. Fondamentalement, j'aurais le nom de la classe dans une chaîne.

189
PeteT

Jetez un coup d’œil à la méthode Activator.CreateInstance .

147
Matt Hamilton

C'est assez simple. Supposons que votre nom de classe est Car et que votre espace de nom est Vehicles, puis transmettez le paramètre en tant que Vehicles.Car qui renvoie un objet de type Car. De cette façon, vous pouvez créer n'importe quelle instance de n'importe quelle classe de manière dynamique.

public object GetInstance(string strFullyQualifiedName)
{         
     Type t = Type.GetType(strFullyQualifiedName); 
     return  Activator.CreateInstance(t);         
}

Si votre Nom pleinement qualifié (c'est-à-dire, Vehicles.Car dans ce cas) se trouve dans un autre assemblage, le Type.GetType sera nul. Dans ce cas, vous parcourez tous les assemblys et recherchez la variable Type. Pour cela, vous pouvez utiliser le code ci-dessous

public object GetInstance(string strFullyQualifiedName)
{
     Type type = Type.GetType(strFullyQualifiedName);
     if (type != null)
         return Activator.CreateInstance(type);
     foreach (var asm in AppDomain.CurrentDomain.GetAssemblies())
     {
         type = asm.GetType(strFullyQualifiedName);
         if (type != null)
             return Activator.CreateInstance(type);
     }
     return null;
 }

Maintenant, si vous voulez appeler un constructeur paramétré procédez comme suit 

Activator.CreateInstance(t,17); // Incase you are calling a constructor of int type

au lieu de

Activator.CreateInstance(t);
54
Sarath Avanavu

J'ai utilisé cette méthode avec succès:

System.Reflection.Assembly.GetExecutingAssembly().CreateInstance(string className)

Vous devez convertir l'objet renvoyé dans le type d'objet souhaité.

52
Ray Li

Ma question aurait probablement dû être plus précise. Je connais en fait une classe de base pour la chaîne, donc résolue par:

ReportClass report = (ReportClass)Activator.CreateInstance(Type.GetType(reportClass));

La classe Activator.CreateInstance a différentes méthodes pour réaliser la même chose de différentes manières. J'aurais pu le lancer sur un objet mais ce qui précède est le plus utile à ma situation.

19
PeteT

Je sais que je suis en retard pour le jeu ... mais la solution que vous recherchez pourrait être la combinaison de ce qui précède et l'utilisation d'une interface pour définir vos objets accessibles au public.

Ensuite, si toutes vos classes ainsi générées implémentent cette interface, vous pouvez simplement transtyper le type d’interface et utiliser l’objet obtenu.

4
Denny

Par exemple, si vous stockez des valeurs de différents types dans un champ de base de données (stocké sous la forme d'une chaîne) et que vous avez un autre champ portant le nom du type (c'est-à-dire String, bool, int, MyClass), vous pourriez, à partir de ce champ, créez une classe de tout type à l'aide du code ci-dessus et remplissez-la avec la valeur du premier champ. Cela dépend bien sûr du type que vous stockez, avec une méthode pour analyser les chaînes dans le type correct. Je l'ai souvent utilisé pour stocker les paramètres de préférences utilisateur dans une base de données.

3
Greg Osborne

Vous semblez avoir décrit la solution que vous souhaitez implémenter, mais pas le problème que vous essayez de résoudre. 

Peut-être essayez-vous de faire quelque chose d'extensibilité, auquel cas je vous suggère de consulter le Managed Extensibility Framework .

3
Jay Bazuzi

Pour créer une instance d'une classe à partir d'un autre projet de la solution, vous pouvez obtenir l'assembly indiqué par le nom d'une classe (par exemple BaseEntity) et créer une nouvelle instance:

  var newClass = System.Reflection.Assembly.GetAssembly(typeof(BaseEntity)).CreateInstance("MyProject.Entities.User");
0
juanpe