111 votes

Création d’instance de type sans constructeur par défaut en c# à l’aide de la réflexion

Prenez la classe suivante (exemple):

class Sometype
{
    int someValue;

    public Sometype(int someValue)
    {
        this.someValue = someValue;
    }
}

Je veux créer une instance de ce type à l'aide de la réflexion:

Type t = typeof(Sometype);
object o = Activator.CreateInstance(t);

Normalement cela va fonctionner, cependant, parce qu' SomeType n'a pas défini un constructeur sans paramètre, l'appel à l' Activator.CreateInstance lèvera une exception de type MissingMethodException avec le message "Pas de constructeur sans paramètre défini pour cet objet." Est-il une autre façon de créer une instance de ce type? Ce serait un peu sucky ajouter sans paramètre constructeurs à tous mes cours.

159voto

Jason Jackson Points 11563

J'ai posté cette réponse ici, mais ici, c'est une réédition car ce n'est pas exactement la même question, mais a la même réponse:

FormatterServices.GetUninitializedObject() permet de créer une instance sans faire appel à un constructeur. J'ai trouvé cette classe à l'aide de Réflecteurs et de creuser par le biais de quelques-uns des principaux .Net classes de sérialisation.

Je l'ai testé à l'aide de l'exemple de code ci-dessous et il semble que ça fonctionne très bien:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Runtime.Serialization;

namespace NoConstructorThingy
{
    class Program
    {
        static void Main(string[] args)
        {
            MyClass myClass = (MyClass)FormatterServices.GetUninitializedObject(typeof(MyClass)); //does not call ctor
            myClass.One = 1;
            Console.WriteLine(myClass.One); //write "1"
            Console.ReadKey();
        }
    }

    public class MyClass
    {
        public MyClass()
        {
            Console.WriteLine("MyClass ctor called.");
        }

        public int One
        {
            get;
            set;
        }
    }
}

73voto

Nick Points 1818

Utilisez cette surcharge de la méthode CreateInstance :

Crée une instance du type spécifié à l’aide du constructeur qui correspond le mieux aux paramètres spécifiés.

Voir : http://msdn.microsoft.com/en-us/library/wcxyzt4d.aspx

26voto

nawfal Points 13500

Quand j'ai comparé les performances de l' (T)FormatterServices.GetUninitializedObject(typeof(T)) c'est plus lent. Dans le même temps compilé expressions vous donnent beaucoup d'améliorations de la vitesse mais ils ne fonctionnent que pour les types avec le constructeur par défaut. J'ai pris une approche hybride:

public static class New<T>
{
    public static readonly Func<T> Instance = Creator();

    static Func<T> Creator()
    {
        Type t = typeof(T);
        if (t == typeof(string))
            return Expression.Lambda<Func<T>>(Expression.Constant(string.Empty)).Compile();

        if (t.HasDefaultConstructor())
            return Expression.Lambda<Func<T>>(Expression.New(t)).Compile();

        return () => (T)FormatterServices.GetUninitializedObject(t);
    }
}

public static bool HasDefaultConstructor(this Type t)
{
    return t.IsValueType || t.GetConstructor(Type.EmptyTypes) != null;
}

Cela signifie la création d'expression est effectivement mis en cache et encourt la peine de seulement la première fois que le type est chargé. Va gérer les types de valeur trop de manière efficace.

Appeler:

MyType me = New<MyType>.Instance();

Notez que (T)FormatterServices.GetUninitializedObject(t) échouent pour la chaîne. D'où un traitement spécial pour chaîne est en place pour renvoyer une chaîne vide.

5voto

permet pas de créer une chaîne non initialisée. Vous pouvez obtenir d’exception :

S’il vous plaît gardez cela à l’esprit.

4voto

Sandeep Datta Points 7344

De bonnes réponses mais inutilisable net compact Framework dot. Voici une solution qui fonctionne sur CF.Net...

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