Comment créer une nouvelle instance de l'objet à partir d'un Type de
On ne peut pas toujours savoir la Type
d'un objet au moment de la compilation, mais peuvent avoir besoin de créer une instance de la Type
. Comment voulez-vous obtenir une nouvelle instance de l'objet à partir d'un Type
?
Vous devez vous connecter pour publier un commentaire.
La
Activator
classe à l'intérieur de la racineSystem
espace de noms est assez puissant.Il y a beaucoup de surcharges pour passer des paramètres au constructeur et à de telles. Consultez la documentation sur:
ou (nouvelle voie)
Voici quelques exemples simples:
ObjectType instance
match de l'OP de l'état "On ne peut pas toujours connaître le type d'un objet au moment de la compilation" ? 😛object instance = Activator.CreateInstance(...);
.La
Activator
classe a un générique variante qui le rend un peu plus facile:Type t
.dynamic
construire qui t autoriser de telles constructions, mais pour la plupart des fins, la réponse encore le couvre.Compilé expression est le meilleur moyen! (pour la performance à plusieurs reprises de créer une instance dans l'exécution).
De la statistique (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:
X
est au moment de l'exécution?Type
.Une mise en œuvre de ce problème consiste à tenter d'appeler le paramètre moins constructeur de Type:
Ici est la même approche, figurant dans une méthode générique:
Son assez simple. Supposons que votre nom de classe est
Car
et de l'espace de noms estVehicles
, puis passez le paramètre queVehicles.Car
qui renvoie un objet de typeCar
. Comme cela, vous pouvez créer une instance d'une classe dynamiquement.Si votre Nom Complet(c'est à dire,
Vehicles.Car
dans ce cas) est dans une autre assemblée, leType.GetType
sera nulle. Dans de tels cas, vous devez faire une boucle par toutes les assemblées et de trouver laType
. Pour cela, vous pouvez utiliser le code ci-dessousEt vous pouvez obtenir de l'instance en appel de la méthode ci-dessus.
Si c'est pour quelque chose qui va être appelé un lot dans une instance de l'application, c'est beaucoup plus rapide à compiler et de mettre en cache dynamique de code au lieu de l'aide de l'activateur ou
ConstructorInfo.Invoke()
. Deux options pour la compilation dynamique sont compilés Les Expressions Linq ou une simpleIL
opcodes etDynamicMethod
. De toute façon, la différence est énorme lorsque vous commencez à recevoir en boucles serrées ou plusieurs appels.Sans utiliser de Réflexion:
Ne serait pas le générique
T t = new T();
travail?Si vous souhaitez utiliser le constructeur par défaut, puis la solution à l'aide de
System.Activator
présentée plus haut est probablement la plus pratique. Toutefois, si le type en manque un constructeur par défaut ou vous devez utiliser un non-par défaut, une option est d'utiliser la réflexion ouSystem.ComponentModel.TypeDescriptor
. Dans le cas de la réflexion, il est suffisant de connaître le nom du type (avec son espace de noms).Exemple à l'aide de la réflexion:
Exemple à l'aide de
TypeDescriptor
:Compte tenu de ce problème, l'Activateur fonctionne quand il est sans paramètre ctor. Si c'est une contrainte d'envisager l'utilisation
Je peux à travers cette question, parce que je cherchais à mettre en œuvre un simple CloneObject méthode pour arbitraire de la classe (avec un constructeur par défaut)
Avec méthode générique, vous pouvez exiger que le type implémente de Nouvelles().
Avec les non-générique assumer le type a un constructeur par défaut et de l'attraper
une exception si elle ne le fait pas.