J'ai un programme C #, comment puis-je vérifier lors de l'exécution si un espace de noms, une classe ou une méthode existe? Aussi, comment instancier une classe en utilisant son nom sous forme de chaîne?
Pseudocode:
string @namespace = "MyNameSpace";
string @class = "MyClass";
string method= "MyMEthod";
var y = IsNamespaceExists(namespace);
var x = IsClassExists(@class)? new @class : null; //Check if exists, instantiate if so.
var z = x.IsMethodExists(method);
Vous pouvez utiliser Type.GetType (chaîne) pour refléter un type. GetType
renverra null si le type est introuvable. Si le type existe, vous pouvez alors utiliser GetMethod
, GetField
, GetProperty
, etc. à partir du Type
retourné pour vérifier si le membre qui vous intéresse en existe.
pdate à votre exemple:
string @namespace = "MyNameSpace";
string @class = "MyClass";
string method= "MyMEthod";
var myClassType = Type.GetType(String.format("{0}.{1}", @namespace, @class));
object instance = myClassType == null ? null : Activator.CreateInstance(myClassType); //Check if exists, instantiate if so.
var myMethodExists = myClassType.GetMethod(method) != null;
Console.WriteLine(myClassType); // MyNameSpace.MyClass
Console.WriteLine(myMethodExists); // True
Il s'agit de la méthode la plus efficace et préférée, en supposant que le type se trouve dans l'assembly en cours d'exécution , dans mscorlib (vous ne savez pas comment .NET Core affecte cela, peut-être System.Runtime
à la place?), ou vous avez un nom qualifié d'assembly pour le type. Si l'argument chaîne que vous passez à GetType
ne satisfait pas à ces trois exigences, GetType
renverra null (en supposant qu'il n'y a pas d'autre type qui chevauche accidentellement ces exigences, oups).
Si vous n'avez pas le nom qualifié d'assembly, vous devrez soit corriger votre approche, soit effectuer une recherche, ce dernier étant potentiellement beaucoup plus lent.
Si nous supposons que vous voulez rechercher le type dans tous les assemblys chargés, vous pouvez faire quelque chose comme ça (en utilisant LINQ):
var type = (from Assembly in AppDomain.CurrentDomain.GetAssemblies()
from type in Assembly.GetTypes()
where type.Name == className
select type);
Bien sûr, il peut y avoir plus que cela, où vous voudrez réfléchir sur les assemblys référencés qui ne sont peut-être pas encore chargés, etc.
Quant à la détermination des espaces de noms, la réflexion ne les exporte pas distinctement. Au lieu de cela, vous devez faire quelque chose comme:
var namespaceFound = (from Assembly in AppDomain.CurrentDomain.GetAssemblies()
from type in Assembly.GetTypes()
where type.Namespace == namespace
select type).Any()
En mettant tout cela ensemble, vous auriez quelque chose comme:
var type = (from Assembly in AppDomain.CurrentDomain.GetAssemblies()
from type in Assembly.GetTypes()
where type.Name == className && type.GetMethods().Any(m => m.Name == methodName)
select type).FirstOrDefault();
if (type == null) throw new InvalidOperationException("Valid type not found.");
object instance = Activator.CreateInstance(type);
Vous pouvez résoudre un Type à partir d'une chaîne en utilisant la méthode Type.GetType (String) . Par exemple:
Type myType = Type.GetType("MyNamespace.MyClass");
Vous pouvez ensuite utiliser cette instance Type pour vérifier si une méthode existe sur le type en appelant la méthode GetMethod (String) . Par exemple:
MethodInfo myMethod = myType.GetMethod("MyMethod");
GetType et GetMethod renvoient null
si aucun type ou méthode n'a été trouvé pour le nom donné, vous pouvez donc vérifier si votre type/méthode existe en vérifiant si votre appel de méthode a renvoyé null ou non.
Enfin, vous pouvez instancier votre type en utilisant Activator.CreateInstance (Type) Par exemple:
object instance = Activator.CreateInstance(myType);
Un mot: Réflexion . À l'exception des espaces de noms, vous devrez analyser ceux des noms de type.
EDIT: Strike that - pour les espaces de noms, vous devrez utiliser la propriété Type.Namespace pour déterminer à quel espace de noms chaque classe appartient. (Voir réponse HackedByChinese pour plus d'informations).