Question

Prenez la classe suivante comme exemple:

class Sometype
{
    int someValue;

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

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

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

Normalement, cela fonctionne, mais parce que SomeType n'a pas défini un constructeur sans paramètre, l'appel à Activator.CreateInstance lancera une exception de type MissingMethodException avec le message « Aucun constructeur parameterless défini pour cet objet. » Est-ce il une autre façon de créer encore une instance de ce type? Ce serait un peu sucky ajouter constructeurs à tous mes sans paramètre classes.

Était-ce utile?

La solution

Je posté à l'origine cette réponse ici , mais voici une réimpression puisque ce n'est pas exactement la même question, mais a la même réponse:

FormatterServices.GetUninitializedObject() va créer une instance sans appeler un constructeur. J'ai trouvé cette classe en utilisant réflecteur et creuser à travers une partie du noyau. cours de sérialisation net.

Je l'ai testé à l'aide du code exemple ci-dessous et il semble que cela 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;
        }
    }
}

Autres conseils

Cette surcharge de la méthode CreateInstance:

public static Object CreateInstance(
    Type type,
    params Object[] args
)
  

crée une instance de la spécifiée   taper à l'aide du constructeur qui correspond le mieux   correspond aux paramètres spécifiés.

Voir: http://msdn.microsoft.com/en-us/ bibliothèque / wcxyzt4d.aspx

Quand je benchmarkée performance de (T)FormatterServices.GetUninitializedObject(typeof(T)) il a été plus lente. En même temps, les expressions compilées vous donnerait de grandes améliorations de la vitesse mais ils ne fonctionnent que pour les types avec constructeur par défaut. Je 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 que la création expression est effectivement mis en mémoire cache et encourt la peine que la première fois que le type est chargé. Traitera des types de valeur trop d'une manière efficace.

Appelez-:

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

Notez que (T)FormatterServices.GetUninitializedObject(t) échouera pour la chaîne. Par conséquent un traitement spécial pour la chaîne est en place pour retourner une chaîne vide.

Les bonnes réponses, mais inutilisable sur le point compact framework net. Voici une solution qui fonctionnera sur CF.Net ...

class Test
{
    int _myInt;

    public Test(int myInt)
    {
        _myInt = myInt;
    }

    public override string ToString()
    {
        return "My int = " + _myInt.ToString();
    }
}

class Program
{
    static void Main(string[] args)
    {
        var ctor = typeof(Test).GetConstructor(new Type[] { typeof(int) });
        var obj = ctor.Invoke(new object[] { 10 });
        Console.WriteLine(obj);
    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top