Il se peut que l'on ne connaisse pas toujours la valeur Type
d'un objet au moment de la compilation, mais il peut être nécessaire de créer une instance de Type
.
Comment obtenir une nouvelle instance d'objet à partir d'un Type
?
c#
.net
performance
reflection
types
tags2k
la source
la source
ObjectType instance
correspond la condition de l'OP "On ne sait pas toujours le type d'un objet au moment de la compilation"? : Pobject instance = Activator.CreateInstance(...);
.La
Activator
classe a une variante générique qui rend cela un peu plus facile:la source
dynamic
construction qui ne permet de telles constructions , mais pour la plupart des cas cette réponse couvre encore.L'expression compilée est le meilleur moyen! (pour que les performances créent plusieurs fois l'instance lors de l'exécution).
Statistiques (2012):
Statistiques (2015, .net 4.5, x64):
Statistiques (2015, .net 4.5, x86):
Statistiques (2017, LINQPad 5.22.02 / x64 / .NET 4.6):
Statistiques (2019, x64 / .NET 4.8):
Statistiques (2019, x64 / .NET Core 3.0):
Code complet:
la source
X
est à l'exécution?Type
.Une implémentation de ce problème consiste à essayer d'appeler le constructeur sans paramètre du type:
Voici la même approche, contenue dans une méthode générique:
la source
C'est assez simple. Supposons que votre nom de classe est
Car
et que l'espace de noms estVehicles
, puis passez le paramètre commeVehicles.Car
lequel renvoie l'objet de typeCar
. Comme cela, vous pouvez créer dynamiquement n'importe quelle instance de n'importe quelle classe.Si votre nom complet (c'est-
Vehicles.Car
à- dire dans ce cas) se trouve dans un autre assembly, leType.GetType
sera nul. Dans de tels cas, vous devez parcourir tous les assemblys et trouver le fichierType
. Pour cela, vous pouvez utiliser le code ci-dessousEt vous pouvez obtenir l'instance en appelant la méthode ci-dessus.
la source
Si c'est pour quelque chose qui sera appelé beaucoup dans une instance d'application, il est beaucoup plus rapide de compiler et de mettre en cache du code dynamique au lieu d'utiliser l'activateur ou
ConstructorInfo.Invoke()
. Les deux options simples pour la compilation dynamique sont les expressions Linq compilées ou certainsIL
opcodesDynamicMethod
simples et . Quoi qu'il en soit, la différence est énorme lorsque vous commencez à effectuer des boucles serrées ou plusieurs appels.la source
Le générique ne
T t = new T();
fonctionnerait -il pas ?la source
Si vous souhaitez utiliser le constructeur par défaut, la solution utilisant
System.Activator
présentée précédemment est probablement la plus pratique. Cependant, si le type n'a pas de constructeur par défaut ou si vous devez en utiliser un autre, alors une option est d'utiliser la réflexion ouSystem.ComponentModel.TypeDescriptor
. En cas de réflexion, il suffit de connaître uniquement le nom du type (avec son espace de noms).Exemple utilisant la réflexion:
Exemple utilisant
TypeDescriptor
:la source
args[]
était exactement ce que je suis venu à cette question pour trouver, merci!Sans utilisation de la réflexion:
la source
Compte tenu de ce problème, l'activateur fonctionnera lorsqu'il y a un ctor sans paramètre. S'il s'agit d'une contrainte, envisagez d'utiliser
la source
la source
Je peux traverser cette question parce que je cherchais à implémenter une méthode CloneObject simple pour une classe arbitraire (avec un constructeur par défaut)
Avec la méthode générique, vous pouvez exiger que le type implémente New ().
Avec non générique, supposez que le type a un constructeur par défaut et interceptez une exception si ce n'est pas le cas.
la source