Pregunta

Tome la siguiente clase como un ejemplo:

class Sometype
{
    int someValue;

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

Entonces quiero crear una instancia de este tipo utilizando la reflexión:

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

Normalmente esto funciona, sin embargo debido a SomeType no ha definido un constructor sin parámetros, la llamada a Activator.CreateInstance lanzará una excepción de tipo MissingMethodException con el mensaje " No constructor sin parámetros definidos para este objeto. " es existe una forma alternativa de aún crear una instancia de este tipo? Sería un poco fastidioso añadir constructores sin parámetros a todas mis clases.

¿Fue útil?

Solución

Iniciado esta respuesta aquí , pero aquí es una reimpresión ya que esto no es exactamente la misma pregunta, pero tiene la misma respuesta:

FormatterServices.GetUninitializedObject() va a crear una instancia sin llamar a un constructor. He encontrado esta clase utilizando Reflector y excavar a través de algunos de núcleo. clases de serialización red.

Lo he comprobado con el código de ejemplo siguiente y parece que funciona muy 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;
        }
    }
}

Otros consejos

Utilice esta sobrecarga del método CreateInstance:

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

Crea una instancia de la especificada   escribir con el constructor que mejor   coincide con los parámetros especificados.

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

Cuando Benchmarked desempeño de (T)FormatterServices.GetUninitializedObject(typeof(T)) que era más lento. Al mismo tiempo, las expresiones recopiladas le daría grandes mejoras en la velocidad a pesar de que sólo funcionan en los modelos con constructor por defecto. Tomé un enfoque híbrido:

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

Esto significa que la expresión se almacena en caché crear eficazmente e incurre en pena sólo la primera vez que se carga el tipo. Se encargará de los tipos de valor también de una manera eficiente.

Lo llaman:

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

Tenga en cuenta que (T)FormatterServices.GetUninitializedObject(t) va a fallar por cadena. Por lo tanto el manejo especial para la cadena está en su lugar para volver cadena vacía.

Las buenas respuestas, pero inservible en punto NET Compact Framework. Aquí es una solución que funcionará en 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);
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top