Frage

Nehmen Sie die folgende Klasse als Beispiel:

class Sometype
{
    int someValue;

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

Ich mag dann eine Instanz dieses Typs mit Reflexion erstellen:

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

Normalerweise funktioniert dies jedoch, weil SomeType nicht einen parameterlosen Konstruktor definiert hat, wird der Anruf an Activator.CreateInstance eine Ausnahme vom Typ MissingMethodException Ausnahme mit der Meldung „ No parameterlosen Konstruktor für dieses Objekt definiert. “ Ist es eine alternative Möglichkeit, um noch eine Instanz dieses Typs zu erstellen? Es wäre ein bisschen sucky parameterlos Bauer alle meine Klassen.

hinzufügen
War es hilfreich?

Lösung

I posted ursprünglich diese Antwort hier , aber hier ist ein Nachdruck, da dies nicht genau die gleiche Frage ist aber die gleiche Antwort hat:

FormatterServices.GetUninitializedObject() eine Instanz erstellen, ohne einen Konstruktor aufrufen. Ich fand diese Klasse unter Verwendung von Reflector und durch einige der Kern zu graben. Net Serialisierung Klassen.

Ich habe es getestet, den Beispielcode unten ein und es sieht aus wie es funktioniert super:

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;
        }
    }
}

Andere Tipps

Mit dieser Überlastung der CreateInstance-Methode:

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

Erstellt eine Instanz des angegebenen   Geben Sie den Konstruktor, die am besten   entspricht den angegebenen Parametern.

Siehe auch: http://msdn.microsoft.com/en-us/ Bibliothek / wcxyzt4d.aspx

Wenn ich Leistung von (T)FormatterServices.GetUninitializedObject(typeof(T)) gebenchmarkt es war langsamer. Zur gleichen Zeit zusammengestellt Ausdrücke würden Sie große Verbesserungen in der Geschwindigkeit geben, obwohl sie nur für Typen mit Standardkonstruktors arbeiten. Ich nahm einen Hybrid-Ansatz:

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;
}

Dies bedeutet, dass der Ausdruck erstellen effektiv zwischengespeichert wird und verursacht Strafe nur beim ersten Mal wird die Art geladen. Werden Werttypen zu auf effiziente Weise handhaben.

Nennen Sie es:

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

Beachten Sie, dass (T)FormatterServices.GetUninitializedObject(t) für String scheitern. Daher spezielle Handhabung für String ist an seinem Platz zu leeren String zurück.

Gute Antworten aber unbrauchbar auf den dot net kompakten Rahmen. Hier ist eine Lösung, auf CF.Net ...

funktioniert
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);
    }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top