Pergunta

Tome a seguinte classe como um exemplo:

class Sometype
{
    int someValue;

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

Então eu quero criar uma instância desse tipo usando a reflexão:

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

Normalmente este trabalho, no entanto, porque SomeType não definiu um construtor sem parâmetros, a chamada para Activator.CreateInstance irá lançar uma exceção do tipo MissingMethodException com a mensagem " No construtor sem parâmetros definidos para este objeto. " é existe uma maneira alternativa para ainda criar uma instância desse tipo? Seria meio sucky para adicionar construtores sem parâmetros para todas as minhas aulas.

Foi útil?

Solução

Eu originalmente publicado esta resposta aqui , mas aqui é uma reedição uma vez que este não é exatamente a mesma pergunta, mas tem a mesma resposta:

FormatterServices.GetUninitializedObject() criará uma instância sem chamar um construtor. Eu encontrei esta classe usando refletor e cavar através de alguns do núcleo. aulas de serialização rede.

Eu testei usando o código de exemplo abaixo e parece que ele funciona muito bem:

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

Outras dicas

Use essa sobrecarga do método CreateInstance:

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

Cria uma instância do especificado digite usando o construtor que melhor coincide com os parâmetros especificados.

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

Quando eu aferido desempenho de (T)FormatterServices.GetUninitializedObject(typeof(T)) era mais lento. Ao mesmo tempo, expressões compiladas lhe daria grandes melhorias de velocidade que eles funcionam apenas para os tipos com construtor padrão. Tomei uma abordagem híbrida:

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

Isto significa que a expressão é criar eficazmente em cache e incorre penalidade apenas a primeira vez que o tipo é carregado. Vai lidar com tipos de valor muito de uma maneira eficiente.

chamá-lo:

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

Note que (T)FormatterServices.GetUninitializedObject(t) falhará para string. manuseio, portanto, especial para a corda está no local para retornar string vazia.

Boas respostas, mas inutilizável em ponto quadro compacto net. Aqui é uma solução que irá funcionar em 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 em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top