En C #, ¿puedo convertir una variable de tipo objeto en una variable de tipo T donde T se define en una variable Tipo?
c#
reflection
types
theringostarrs
fuente
fuente
Type
variable, puede usar la reflexión para crear una instancia de ese tipo. Y luego puede usar un método genérico para devolver el tipo que desee deduciéndolo de un parámetro de ese tipo. Desafortunadamente, cualquier método de reflexión que cree una instancia de un tipo tendrá un tipo de retornoobject
, por lo que suCastByExample
método genérico también lo usaráobject
. Entonces, realmente no hay forma de hacer esto, e incluso si lo hubiera, ¿qué harías con el objeto recién lanzado? No podías usar sus métodos ni nada porque no conoces su tipo.object
odynamic
. Si desea cargar dinámicamente módulos externos, puede hacer que las clases compartan una interfaz común y convertir el objeto en eso. Si no controla el código de terceros, cree pequeños contenedores e implemente la interfaz en eso.Respuestas:
Aquí hay un ejemplo de un elenco y un converso:
Editar:
Algunas personas en los comentarios dicen que esta respuesta no responde la pregunta. Pero la línea
(T) Convert.ChangeType(input, typeof(T))
proporciona la solución. ElConvert.ChangeType
método intenta convertir cualquier objeto al tipo proporcionado como segundo argumento.Por ejemplo:
He escrito la respuesta con los genéricos, porque creo que es un muy probable signo de olor código cuando se desea fundido
a something
aa something else
sin manipular un tipo real. Con interfaces adecuadas que no deberían ser necesarias el 99.9% de las veces. Quizás haya algunos casos extremos cuando se trata de reflexionar que podría tener sentido, pero recomendaría evitar esos casos.Edición 2:
Pocos consejos adicionales:
object
odynamic
variable.fuente
T
como tal.Convert.ChangeType(input, typeof(T));
da la solución. Puede reemplazar fácilmentetypeof(T)
con una variable de tipo existente. Una mejor solución (si es posible) sería evitar el tipo dinámico por completo.T
que no está disponible.T
pero aún así solo obtienes unobject
como referencia. hmm, encontré la pregunta interesante en la premisa de que OP solo tiene laType
variable y ninguna otra información. Como si la firma del método esConvert(object source, Type destination)
:) Sin embargo me sale ur puntoOtras respuestas no mencionan el tipo "dinámico". Por lo tanto, para agregar una respuesta más, puede usar el tipo "dinámico" para almacenar su objeto resultante sin tener que convertir el objeto convertido con un tipo estático.
Tenga en cuenta que con el uso de "dinámico" el compilador pasa por alto la comprobación de tipo estático que podría introducir posibles errores de tiempo de ejecución si no tiene cuidado.
fuente
Aquí está mi método para convertir un objeto pero no a una variable de tipo genérico, sino a una
System.Type
dinámica:Creo una expresión lambda en tiempo de ejecución usando
System.Linq.Expressions
, de tipoFunc<object, object>
, que desempaqueta su entrada, realiza la conversión de tipo deseada y luego da el resultado encuadrado. Se necesita uno nuevo no solo para todos los tipos que se lanzan, sino también para los tipos que se lanzan (debido al paso de desempaquetado). La creación de estas expresiones requiere mucho tiempo, debido a la reflexión, la compilación y la construcción dinámica de métodos que se realiza bajo el capó. Afortunadamente, una vez creadas, las expresiones se pueden invocar repetidamente y sin sobrecarga, por lo que guardo en caché cada una.Tenga en cuenta que esto no es mágico. La conversión no se produce en el código, como ocurre con la
dynamic
palabra clave, solo se convierten los datos subyacentes del objeto. En el momento de la compilación, todavía tenemos que determinar minuciosamente exactamente qué tipo de objeto podría ser, lo que hace que esta solución sea poco práctica. Escribí esto como un truco para invocar operadores de conversión definidos por tipos arbitrarios, pero tal vez alguien por ahí pueda encontrar un mejor caso de uso.fuente
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
. No puedes lanzar usando la sintaxis de conversión normal si todo lo que tienes es el objeto Tipo. Si desea poder usar el objeto como algún tipo T en tiempo de compilación, no en tiempo de ejecución, debe convertirlo usando una variable de tipo o solo el nombre de tipo real. Puedes hacer lo primero usando la respuesta de Zaphrax.Dejando a un lado el boxeo y el desempaquetado por simplicidad, no hay una acción de tiempo de ejecución específica involucrada en el reparto a lo largo de la jerarquía de herencia. Es sobre todo una cuestión de tiempo de compilación. Esencialmente, un elenco le dice al compilador que trate el valor de la variable como otro tipo.
¿Qué podrías hacer después del elenco? No conoce el tipo, por lo que no podrá llamar a ningún método. No habría nada especial que pudieras hacer. Específicamente, puede ser útil solo si conoce los tipos posibles en el momento de la compilación, lo convierte manualmente y maneja cada caso por separado con
if
declaraciones:fuente
¿Como pudiste? Necesita una variable o campo de tipo T donde pueda almacenar el objeto después del lanzamiento, pero ¿cómo puede tener esa variable o campo si conoce T solo en tiempo de ejecución? Entonces, no, no es posible.
fuente
CastTo
métodoObject
?Cuando se trata de lanzar a Enum, escriba:
Y lo llamarás así:
Esto fue esencial para mí en caso de obtener el valor del atributo Descripción de varios tipos de enumeración por valor int:
y entonces:
Alternativamente (mejor enfoque), dicho casting podría verse así:
fuente
Después de no encontrar nada para sortear la excepción "El objeto debe implementar IConvertible" al usar la respuesta de Zyphrax (excepto para implementar la interfaz) .. Intenté algo un poco poco convencional y trabajé para mi situación.
Usando el paquete Newtonsoft.Json nuget ...
fuente
Daño, el problema es que no tienes una T.
solo tiene una variable Tipo.
Sugerencia para MS, si pudieras hacer algo como
TryCast<typeof(MyClass)>
si resolvería todos nuestros problemas
fuente
Nunca entenderé por qué necesita hasta 50 reputación para dejar un comentario, pero solo tenía que decir que la respuesta de @Curt es exactamente lo que estaba buscando y espero que alguien más.
En mi ejemplo, tengo un ActionFilterAttribute que estaba usando para actualizar los valores de un documento de parche json. No sabía cuál era el modelo T para el documento de parche, tuve que serializarlo y deserializarlo en un JsonPatchDocument simple, modificarlo, luego porque tuve el tipo, serializarlo y deserializarlo nuevamente al tipo.
fuente
fuente
incluso más limpio:
fuente
Si necesita lanzar objetos en tiempo de ejecución sin conocer el tipo de destino, puede usar la reflexión para hacer un convertidor dinámico.
Esta es una versión simplificada (sin el método generado de almacenamiento en caché):
entonces puedes llamarlo:
fuente