916 votes

Comment créer une nouvelle instance d'objet à partir d'un Type

On ne sait pas toujours Type d'un objet au moment de la compilation, mais il peut être nécessaire de créer une instance de l'objet Type .

Comment obtenir une nouvelle instance d'objet à partir d'un fichier Type ?

1051voto

Karl Seguin Points 10566

Le site Activator au sein de la classe Root System est assez puissant.

Il y a beaucoup de surcharges pour passer des paramètres au constructeur et autres. Consultez la documentation à l'adresse suivante :

http://msdn.microsoft.com/en-us/library/system.activator.createinstance.aspx

ou (nouveau chemin)

https://docs.microsoft.com/en-us/dotnet/api/system.activator.createinstance

Voici quelques exemples simples :

ObjectType instance = (ObjectType)Activator.CreateInstance(objectType);

ObjectType instance = (ObjectType)Activator.CreateInstance("MyAssembly","MyNamespace.ObjectType");

13 votes

Vous devez appeler 'Unwrap()' pour obtenir le type d'objet que vous souhaitez : ConcreteType instance = (ConcreteType)Activator.CreateInstance(objectType).Unwrap() ;

6 votes

Comment ObjectType instance correspond à la condition de l'OP "On ne peut pas toujours connaître le type d'un objet au moment de la compilation" ? :P

1 votes

@MA-Maddin ok alors, object instance = Activator.CreateInstance(...); .

188voto

Konrad Rudolph Points 231505
ObjectType instance = (ObjectType)Activator.CreateInstance(objectType);

Le site Activator a une variante générique qui facilite un peu les choses :

ObjectType instance = Activator.CreateInstance<ObjectType>();

11 votes

@Kevin Bien sûr. Une telle opération ne peut pas travailler dans un langage statiquement typé parce que cela n'a pas de sens. Vous ne pouvez pas invoquer des méthodes sur un objet de type inconnu. Entre-temps (= depuis que j'ai écrit cette réponse), C# a obtenu la fonction dynamic construire qui fait permettent de telles constructions mais, dans la plupart des cas, cette réponse les couvre toujours.

2 votes

@KonradRudolph Pas tout à fait vrai. D'abord du c# fait vous permettent de créer de nouveaux types au moment de l'exécution. Vous ne pouvez simplement rien appeler sur eux d'une manière statiquement sûre . Donc oui, vous avez à moitié raison. Mais de manière plus réaliste, vous en avez besoin lorsque vous chargez des assemblages au moment de l'exécution, ce qui signifie que le type n'est pas connu au moment de la compilation. C# serait sévèrement limité si vous ne pouviez pas faire cela. Vous venez d'ailleurs de le prouver vous-même : comment la méthode Activator qui prend une instance de type fonctionne-t-elle autrement ? Lorsque MS a écrit la classe Activator, ils n'avaient aucune connaissance à la compilation des futurs types que les utilisateurs écriraient.

1 votes

@AnorZaken Mon commentaire ne dit rien sur la création de types au moment de l'exécution. Bien sûr, vous pouvez le faire, mais vous ne pouvez pas les utiliser statiquement dans le même contexte (vous pouvez héberger un programme complet compilé statiquement, bien sûr). C'est tout ce que mon commentaire dit.

47voto

tags2k Points 11036

Une façon de résoudre ce problème est d'essayer d'appeler le constructeur sans paramètre du Type :

    public static object GetNewObject(Type t)    {        try        {            return t.GetConstructor(new Type[] { }).Invoke(new object[] { });        }        catch        {            return null;        }    }

Voici la même approche, contenue dans une méthode générique :

    public static T GetNewObject<T>()    {        try        {            return (T)typeof(T).GetConstructor(new Type[] { }).Invoke(new object[] { });        }        catch        {            return default(T);        }    }

18voto

Thomas G. Mayfield Points 5208

S'il s'agit d'un élément qui sera souvent appelé dans une instance d'application, il est beaucoup plus rapide de compiler et de mettre en cache le code dynamique plutôt que d'utiliser l'activateur ou l'option ConstructorInfo.Invoke() . Deux options faciles pour la compilation dynamique sont compilées Expressions Linq ou un simple IL opcodes et DynamicMethod . Quoi qu'il en soit, la différence est énorme lorsque vous commencez à vous retrouver dans des boucles serrées ou des appels multiples.

10voto

boomhauer Points 2392

Le générique ne serait-il pas T t = new T(); travail ?

13 votes

En fait, ce serait le cas dans une classe/méthode générique, mais pas pour un "type" donné.

2 votes

Suppose que le type T possède la contrainte 'new()'.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X