2011-12-18 13 views
18

Lo que quiero hacer es algo como esto:C# Reflection: Cómo obtener el tipo de Nullable <int>?

switch(myObject.GetType().GetProperty("id")) 
{ 
    case ??: 
     // when Nullable<Int32>, do this 
    case ??: 
     // when string, do this 
    case ??: 
     // when Nullable<bool>, do this 

¿Qué camino bajo object.GetType() tendría el nombre de la cadena del tipo de datos que he podido comparar el uso de una declaración de caso? Necesito saber el tipo para poder tener uno de muchos Convert.ToInt32 (cadena) que establecerá el valor de myObject usando Reflection.

+1

Esto definitivamente hace las cosas mal. ¿Por qué no puedes tomar ventaja del polimorfismo, en lugar de usar una declaración de cambio gigante? –

+0

Si está sugiriendo crear varias funciones con diferentes tipos de parámetros, podría. En este caso, estoy copiando un conjunto de propiedades de diferentes tipos de un objeto a otro donde uno siempre es un tipo de cadena. Entonces, necesito convertir el valor para asignarlo. Eso y tengo muy poca experiencia con Reflection. –

+0

@CodyGray podría estar haciendo algo con respecto a la reflexión, por ejemplo, escribiendo su propio ORM. O escribiendo un serializador personalizado para todos estos DAO, nunca se sabe. – nawfal

Respuesta

8

Actualización: Parece que C# 7 admitirá el encendido de Type s como el que intentaba hacer esta pregunta estaba tratando de hacer. Sin embargo, es un poco diferente, así que ten cuidado con las minas de sintaxis.

No es necesario un nombre de cadena para compararlo:

if (myObject.GetType().GetProperty("id").PropertyType == typeof(Nullable<Int32>)) 
    // when Nullable<Int32>, do this 
else if (myObject.GetType().GetProperty("id").PropertyType == typeof(string)) 
    // when string, do this 
else if (myObject.GetType().GetProperty("id").PropertyType == typeof(Nullable<bool>)) 
    // when Nullable<bool>, do this 
+1

¿Estás seguro de que comparas .GetType() con typeof (Nullable ) o es una propiedad bajo GetType()? Asumiendo int? y Nullable son del mismo tipo, a.GetType()! = typeof (Nullable ). –

+0

Probablemente tenga que hacer esto con sentencias 'if', en lugar de en una instrucción' switch'. Pero, como tú, nunca he hecho esto antes. Parece un antipatrón para mí. –

+0

VS studio tendrá un ataque de pánico sobre el interruptor de código anterior (myObject.GetType()) mostrará un error IDE de "Valor del tipo integral esperado" y el tipo de caso (XXX) mostrará un error IDE de "Se espera valor constante" – heads5150

0

Como se ha dicho @Cody gris si las declaraciones probablemente sería la mejor manera

var t = myObject.GetType(); 

if (t == typeof(Nullable<int>)) 
{ } 
else if (t == typeof(string)) 
{} 
else if (t==typeof(Nullable<bool>)) 
{} 
+2

curiosamente, cuando 'int? a = 3' luego 'typeof (a)' es "System.Int32" –

+1

@ Dr.Zim: ver explicación aquí: http://stackoverflow.com/questions/785358/nullable-type-is-not-a-nullable -type –

+1

@ Dr.Zim 'typeof (a)' ni siquiera compila. Es 'a.GetType()' que devuelve 'int'. – CodesInChaos

44

He estado usando el siguiente tipo de código para comprobar si el tipo es anulable y para obtener el tipo real:

if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>)) 
{ 
    return Nullable.GetUnderlyingType(type); 
} 

Si el tipo es, por ejemplo Nullable este código devuelve la parte int (tipo subyacente). Si solo necesita convertir un objeto en un tipo específico, puede usar el método System.Convert.ChangeType.

+0

+1 y vale la pena señalar que este método hace la misma verificación dentro y devuelve null si el tipo dado no es' typeof (Nullable <>) 'por lo que hacer una comprobación nula después en lugar de la instrucción if también funcionaría. – Connell

16

La pregunta es muy confusa. ¿Es "myObject" el objeto que podría ser un int nullable? ¿O es la propiedad "id" posiblemente de tipo nullable int?

Si el primero, su pregunta no puede ser respondida porque presupone una falsedad. No existe una caja nullable int. Observo que todas las respuestas que proponen if (myobject.GetType() == typeof(int?)) son incorrectas; la condición nunca será verdadera.

Cuando convierte un int nullable al objeto, se convierte en una referencia nula (si el int nullable no tiene valor) o se convierte en un int encuadrado. No hay forma de determinar si un objeto contiene un int nullable porque un objeto never contiene un int nullable.

Si es el último, compare el tipo de propiedad con typeof(int?). No puedes usar un interruptor; solo se pueden usar constantes para los casos de conmutación y los tipos no son constantes.

Dicho todo esto, este es un mal olor a código. ¿Por qué estás usando la reflexión en primer lugar?

+0

Actualización: en C# 7, las instrucciones de conmutación ya no requieren expresiones constantes :) –

+0

Y proporcionan un mecanismo para activar los tipos. Esa característica se propuso por primera vez en ... 2001? Creo. Entonces, 16 años, no está mal. –

2

En .net, las instancias de tipos de valores son solo colecciones de bits, sin información de tipo asociada. Para cada tipo de valor que no sea Nullable<T>, sin embargo, el sistema también genera automáticamente un tipo de clase correspondiente que deriva de System.ValueType. Existe una conversión de ampliación del tipo de valor al tipo de clase generado automáticamente, y una conversión de reducción del tipo de clase generado automáticamente al tipo de valor. En el caso de Nullable<T>, no hay un tipo de clase autogenerado correspondiente con conversiones a/del tipo de valor; en su lugar, existen conversiones de ampliación en ambas direcciones entre Nullable<T> y el tipo de clase asociado con T.

Por lo que puedo decir, este extraño comportamiento se implementó para permitir comparaciones entre null y Nullable<T> vacío para devolver verdadero.

Cuestiones relacionadas