Domanda

Prendere la seguente classe come esempio:

class Sometype
{
    int someValue;

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

Allora voglio creare un'istanza di questo tipo utilizzando la riflessione:

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

Normalmente questo funzionerà, tuttavia, a causa SomeType non ha definito un costruttore senza parametri, la chiamata a Activator.CreateInstance un'eccezione di tipo MissingMethodException con il messaggio " Non senza parametri costruttore definito per questo oggetto. " Is c'è un modo alternativo per creare ancora un'istanza di questo tipo? Sarebbe un po sucky aggiungere costruttori senza parametri a tutti i miei corsi.

È stato utile?

Soluzione

I originariamente postato questa risposta qui , ma qui è una ristampa dal momento che questo non è esattamente la stessa domanda, ma ha la stessa risposta:

FormatterServices.GetUninitializedObject() creerà un'istanza senza chiamare un costruttore. Ho trovato questa classe utilizzando Riflettore e scavando attraverso alcuni del nucleo. classi di serializzazione netti.

Ho provato utilizzando il codice di esempio riportato di seguito e sembra che funziona alla grande:

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

Altri suggerimenti

Utilizzare questo overload del metodo CreateInstance:

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

Crea un'istanza specificata   digitare utilizzando il costruttore che meglio   corrisponde ai parametri specificati.

See: http://msdn.microsoft.com/en-us/ biblioteca / wcxyzt4d.aspx

Quando benchmark prestazioni di (T)FormatterServices.GetUninitializedObject(typeof(T)) è stato più lento. Allo stesso tempo, le espressioni compilati darebbe grandi miglioramenti di velocità anche se funzionano solo per i tipi con costruttore di default. Ho preso un approccio ibrido:

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

Questo significa l'espressione creare è effettivamente memorizzato nella cache e incorre pena solo la prima volta il tipo viene caricato. Gestirà i tipi di valore anche in un modo efficiente.

Lo chiamano:

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

Si noti che (T)FormatterServices.GetUninitializedObject(t) non riuscirà per la stringa. trattamento Quindi speciale per corda è posto per tornare stringa vuota.

Le buone risposte, ma inutilizzabile sul quadro compatto dot net. Ecco una soluzione che funziona su 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);
    }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top