Tomar la clase siguiente como ejemplo:

class Sometype
{
    int someValue;

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

Luego quiero crear una instancia de este tipo de uso de la reflexión:

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

Normalmente esto va a funcionar, sin embargo, debido a SomeType no ha definido un constructor sin parámetros, la llamada a Activator.CreateInstance producirá una excepción de tipo MissingMethodException con el mensaje «Ningún constructor sin parámetros definidos para este objeto.» Hay una forma alternativa de crear una instancia de este tipo? Sería un poco sucky para agregar constructores sin parámetros para todas mis clases.

  • FormatterServices.GetUninitializedObject no permiten crear la cadena sin inicializar. Usted puede obtener excepción: System.ArgumentException: Uninitialized Strings cannot be created. por Favor, mantenga esto en mente.
  • Gracias por el aviso, pero ya estoy de manipulación de cadenas de caracteres y tipos básicos por separado.
InformationsquelleAutor Aistina | 2008-12-24

4 Comentarios

  1. 130

    Originalmente publicado 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() creará una instancia sin necesidad de llamar a un constructor. He encontrado esta clase mediante el uso de Reflector y cavar a través de algunos de los principales .Net clases de serialización.

    He probado usando el siguiente código de ejemplo 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;
            }
        }
    }

  2. 71

    Utilizar esta sobrecarga del método CreateInstance:

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

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

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

    • Esta solución simplifica demasiado el problema. ¿Qué pasa si no sé cuál es mi tipo y yo estoy diciendo «basta con crear un objeto del Tipo en este Tipo de variable»?
  3. 19

    Cuando me punto de referencia rendimiento de (T)FormatterServices.GetUninitializedObject(typeof(T)) fue más lento. Al mismo tiempo, compilado expresiones dan grandes mejoras en la velocidad a pesar de trabajar sólo para los tipos con el constructor por defecto. Me 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 el crear la expresión es, efectivamente, almacena en caché y se incurre en la pena de sólo la primera vez que el tipo se carga. Manejará los tipos de valor que también en una manera eficiente.

    Llaman:

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

    Nota que (T)FormatterServices.GetUninitializedObject(t) fallará para la cadena. Por lo tanto un tratamiento especial para la cadena está en el lugar de devolver una cadena vacía.

    • Es extraño cómo un vistazo a una sola línea de código puede guardar de un día. Gracias, señor! Rendimiento de las razones que me llevó a tu post y el truco está hecho 🙂 FormatterServices y Activador de las clases son de bajo rendimiento en comparación con compilado de expresiones, qué lástima que uno encuentra Activadores de todo el lugar.
    • Con respecto a su manejo especial para la cadena, sé que lo haría fallar por cadena sin este manejo especial, pero sólo quiero saber: ¿funcionará todo otros tipos?
    • por desgracia, no. El ejemplo dado es muy simple y .NET tiene muchos tipos diferentes de tipos. Por ejemplo, considere la posibilidad de, si se pasa de un tipo de delegado cómo va usted a dar un ejemplo? O si por el contrario, constructor de lanza de lo que se puede hacer al respecto? Muchas maneras diferentes de manejar. Yo había partir de la respuesta a esta actualizado a manejar mucho más escenarios en mi biblioteca. No es publicado en cualquier lugar por ahora.
  4. 4

    Buenas respuestas, pero no puede utilizarse en el dot net compact framework. Aquí es una solución que se va a trabajar 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);
        }
    }
    • Esta es la forma en que yo llamaría un no-constructor predeterminado. No estoy seguro de que me quiera crear un objeto de no llamar a un constructor en todos.
    • Puede que desee crear un objeto sin necesidad de llamar a los constructores si usted está escribiendo personalizado serializadores.
    • Sí, esa es la exacta escenario de caso de uso de esta pregunta era para el 🙂
    • Tal vez usted podría agregar esta información a la pregunta? La mayoría de la gente estaría en contra de la creación de objetos sin necesidad de llamar a sus ctors y se toman el tiempo para discutir con usted acerca de eso, pero el caso de uso, en realidad lo justifique, por lo que creo que es muy relevante para la pregunta en sí misma.

Dejar respuesta

Please enter your comment!
Please enter your name here