Em C #, posso converter uma variável do tipo objeto em uma variável do tipo T, onde T é definido na variável Type?
c#
reflection
types
theringostarrs
fonte
fonte
Type
variável, poderá usar a reflexão para criar uma instância desse tipo. E então você pode usar um método genérico para retornar o tipo desejado, deduzindo-o de um parâmetro desse tipo. Infelizmente, qualquer método de reflexão que crie uma instância de um tipo terá um tipo de retornoobject
; portanto, seuCastByExample
método genérico também será usadoobject
. Portanto, não há realmente nenhuma maneira de fazer isso, e mesmo que houvesse, o que você faria com o objeto recém-lançado? Você não pode usar seus métodos ou qualquer coisa, porque você não conhece seu tipo.object
oudynamic
. Se você deseja carregar dinamicamente módulos externos, é possível que as classes compartilhem uma interface comum e convertam o objeto para isso. Se você não controlar o código de terceiros, crie pequenos wrappers e implemente a interface.Respostas:
Aqui está um exemplo de elenco e de conversão:
Editar:
Algumas pessoas nos comentários dizem que esta resposta não responde à pergunta. Mas a linha
(T) Convert.ChangeType(input, typeof(T))
fornece a solução. OConvert.ChangeType
método tenta converter qualquer objeto no tipo fornecido como o segundo argumento.Por exemplo:
Eu escrevi a resposta com os genéricos, porque eu acho que é muito provável sinal de cheiro de código quando você quer elenco
a something
paraa something else
sem lidar com um tipo real. Com interfaces adequadas que não devem ser necessárias 99,9% das vezes. Talvez existam alguns casos extremos quando se trata de reflexão que possa fazer sentido, mas eu recomendaria evitar esses casos.Edição 2:
Algumas dicas extras:
object
oudynamic
variável.fonte
T
como tal.Convert.ChangeType(input, typeof(T));
dá a solução. Você pode substituir facilmentetypeof(T)
por uma variável de tipo existente. Uma solução melhor (se possível) seria impedir o tipo dinâmico todos juntos.T
qual não está disponível.T
mas ainda assim você recebe umobject
como referência. hmm, achei a pergunta interessante na premissa de que o OP tem apenas aType
variável e nenhuma outra informação. Como se a assinatura do método éConvert(object source, Type destination)
:) No entanto eu recebo ur pontoOutras respostas não mencionam o tipo "dinâmico". Portanto, para adicionar mais uma resposta, você pode usar o tipo "dinâmico" para armazenar o objeto resultante sem precisar converter o objeto convertido com um tipo estático.
Lembre-se de que, com o uso de "dinâmico", o compilador está ignorando a verificação de tipo estático, que pode introduzir possíveis erros de tempo de execução se você não tomar cuidado.
fonte
Aqui está o meu método para converter um objeto, mas não para uma variável de tipo genérico, e sim para uma
System.Type
dinâmica:Crio uma expressão lambda em tempo de execução usando
System.Linq.Expressions
, do tipoFunc<object, object>
, que desmarca sua entrada, executa a conversão de tipo desejada e, em seguida, fornece o resultado em caixa. Um novo é necessário não apenas para todos os tipos que são convertidos, mas também para os tipos que são convertidos (devido à etapa de remoção da caixa de seleção). Criar essas expressões consome muito tempo, devido à reflexão, à compilação e à construção dinâmica de métodos que são feitas sob o capô. Felizmente, uma vez criadas, as expressões podem ser invocadas repetidamente e sem sobrecarga, então eu cache cada uma.Note que isso não é mágico. A transmissão não ocorre no código, como ocorre com a
dynamic
palavra - chave, apenas os dados subjacentes do objeto são convertidos. No momento da compilação, ainda temos que descobrir com precisão qual o tipo de nosso objeto, tornando essa solução impraticável. Eu escrevi isso como um hack para chamar operadores de conversão definidos por tipos arbitrários, mas talvez alguém por aí possa encontrar um melhor caso de uso.fonte
using System.Linq.Expressions;
Type t = typeof(MyGeneric<>).MakeGenericType(obj.OutputType); var a = (t)Convert.ChangeType(obj, t); var b = (t)Caster.Cast(t, obj);
Type
. Você não pode transmitir usando a sintaxe de transmissão normal se tudo o que tiver é o objeto Type. Se você quiser usar o objeto como algum tipo T no tempo de compilação, não no tempo de execução, precisará convertê-lo usando uma variável de tipo ou apenas o nome do tipo real. Você pode fazer o primeiro usando a resposta de Zaphrax.Pondo de lado o boxe e o unboxing para simplificar, não há nenhuma ação específica de tempo de execução envolvida na transmissão ao longo da hierarquia de herança. É principalmente uma coisa de tempo de compilação. Essencialmente, uma conversão diz ao compilador para tratar o valor da variável como outro tipo.
O que você poderia fazer depois do elenco? Você não conhece o tipo, portanto não poderá chamar nenhum método. Não haveria nada de especial que você pudesse fazer. Especificamente, ele pode ser útil apenas se você conhecer os tipos possíveis em tempo de compilação, convertê-lo manualmente e manipular cada caso separadamente com
if
instruções:fonte
Como você pode fazer aquilo? Você precisa de uma variável ou campo do tipo T em que possa armazenar o objeto após a conversão, mas como pode ter essa variável ou campo se conhecer T somente em tempo de execução? Então, não, não é possível.
fonte
CastTo
métodoObject
?Quando se trata de transmitir para o tipo Enum:
E você vai chamar assim:
Isso foi essencial para mim no caso de obter o valor do atributo Description de vários tipos de enumeração pelo valor int:
e depois:
Como alternativa (melhor abordagem), esse elenco poderia ser assim:
fonte
Depois de não encontrar nada para contornar a exceção "O objeto deve implementar o IConvertible" ao usar a resposta do Zyphrax (exceto para implementar a interface) .. Tentei algo um pouco não convencional e trabalhei para a minha situação.
Usando o pacote nuget Newtonsoft.Json ...
fonte
Dano, o problema é que você não tem um T.
você só tem uma variável Type.
Dica para a MS, se você pudesse fazer algo como
TryCast<typeof(MyClass)>
se resolveria todos os nossos problemas.
fonte
Eu nunca vou entender por que você precisa de até 50 reputação para deixar um comentário, mas eu apenas tinha que dizer que a resposta @Curt é exatamente o que eu estava procurando e, espero, outra pessoa.
No meu exemplo, tenho um ActionFilterAttribute que estava usando para atualizar os valores de um documento de patch json. Eu não sabia qual era o modelo T para o documento de correção, pois precisava serializá-lo e desserializá-lo para um JsonPatchDocument simples, modificá-lo e, em seguida, porque eu tinha o tipo, serializar e desserializar novamente para o tipo.
fonte
fonte
ainda mais limpo:
fonte
Se você precisar converter objetos em tempo de execução sem saber o tipo de destino, poderá usar a reflexão para criar um conversor dinâmico.
Esta é uma versão simplificada (sem o método gerado em cache):
então você pode chamá-lo:
fonte