Nem sempre é possível conhecer o Type
objeto em tempo de compilação, mas pode ser necessário criar uma instância do Type
.
Como você obtém uma nova instância de objeto de a Type
?
c#
.net
performance
reflection
types
tags2k
fonte
fonte
ObjectType instance
corresponde à condição do OP "Nem sempre é possível saber o tipo de um objeto no tempo de compilação"? : Pobject instance = Activator.CreateInstance(...);
.A
Activator
classe possui uma variante genérica que facilita um pouco isso:fonte
dynamic
conceito que faz permitir que tais construções, mas na maioria dos casos esta resposta ainda cobre.Expressão compilada é a melhor maneira! (para desempenho para criar repetidamente instância em tempo de execução).
Estatísticas (2012):
Estatísticas (2015, .net 4.5, x64):
Estatísticas (2015, .net 4.5, x86):
Estatísticas (2017, LINQPad 5.22.02 / x64 / .NET 4.6):
Estatísticas (2019, x64 / .NET 4.8):
Estatísticas (2019, x64 / .NET Core 3.0):
Código completo:
fonte
X
é em tempo de execução?Type
.Uma implementação desse problema é tentar chamar o construtor sem parâmetros do Type:
Aqui está a mesma abordagem, contida em um método genérico:
fonte
É bem simples. Suponha que seu nome de classe seja
Car
e o namespace sejaVehicles
, depois passe o parâmetro como oVehicles.Car
que retorna o objeto do tipoCar
. Assim, você pode criar qualquer instância de qualquer classe dinamicamente.Se o seu nome completo (ou seja,
Vehicles.Car
neste caso) estiver em outra montagem, o valorType.GetType
será nulo. Nesses casos, você percorre todas as montagens e encontra oType
. Para isso você pode usar o código abaixoE você pode obter a instância chamando o método acima.
fonte
Se isso é para algo que será chamado muito em uma instância de aplicativo, é muito mais rápido compilar e armazenar em cache o código dinâmico em vez de usar o ativador ou
ConstructorInfo.Invoke()
. Duas opções fáceis para compilação dinâmica são Linq Expressions compiladas ou algunsIL
opcodes eDynamicMethod
. De qualquer forma, a diferença é enorme quando você começa a fazer loops apertados ou várias chamadas.fonte
O genérico não
T t = new T();
funcionaria?fonte
Se você deseja usar o construtor padrão, a solução usada
System.Activator
anteriormente é provavelmente a mais conveniente. No entanto, se o tipo não possuir um construtor padrão ou você precisar usar um não padrão, uma opção é usar reflexão ouSystem.ComponentModel.TypeDescriptor
. Em caso de reflexão, basta saber apenas o nome do tipo (com seu espaço para nome).Exemplo usando reflexão:
Exemplo usando
TypeDescriptor
:fonte
args[]
Foi exatamente o que cheguei a esta pergunta para encontrar, obrigado!Sem uso de Reflexão:
fonte
Dado esse problema, o Ativador funcionará quando houver um ctor sem parâmetros. Se for uma restrição, considere usar
fonte
fonte
Posso resolver essa questão porque estava procurando implementar um método CloneObject simples para classe arbitrária (com um construtor padrão)
Com o método genérico, você pode exigir que o tipo implemente New ().
Com não genérico, assuma que o tipo tem um construtor padrão e, se não o fizer, captura uma exceção.
fonte