2012-02-24 13 views
15

que tienen el código abajo y que había necesidad de convertir una cadena a un tipo que también se especifica a partir de la secuencia:Cómo convertir una cadena a un tipo anulable que se determina en tiempo de ejecución?

Type t = Type.GetType("System.Nullable`1[[System.DateTime, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]"); 

      object d = Convert.ChangeType("2012-02-23 10:00:00", t); 

me sale el mensaje de error a continuación:

Invalid cast from 'System.String' to 'System.Nullable`1[[System.DateTime, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]'. 

¿Cómo sería ese ser agradablemente posible?

sé una manera fea sería comprobar si el tipo es anulable si usando:

Type possiblyNullableType = Type.GetType("System.Nullable`1[[System.DateTime, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]"); 

    var underlyingType = Nullable.GetUnderlyingType(possiblyNullableType); 

    Object result; 

    // if it's null, it means it wasn't nullable 
    if (underlyingType != null) 
    { 
     result = Convert.ChangeType("2012-02-23 10:00:00", underlyingType); 
    } 

Habría alguna manera mejor?

Gracias,

Respuesta

29

Hay dos problemas .

En primer lugar, Convert.ChangeType simplemente no admite los tipos que aceptan nulos.

En segundo lugar, incluso si lo hizo, al encajonar el resultado (asignándolo a un object), ya lo estaría convirtiendo a DateTime.

Usted podría casos especiales tipos anulables:

string s = "2012-02-23 10:00:00"; 
Type t = Type.GetType("System.Nullable`1[[System.DateTime, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]"); 
object d; 

if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>)) 
{ 
    if (String.IsNullOrEmpty(s)) 
     d = null; 
    else 
     d = Convert.ChangeType(s, t.GetGenericArguments()[0]); 
} 
else 
{ 
    d = Convert.ChangeType(s, t); 
} 
+0

¿Por qué debería verificar t.IsGenericType? la parte t.GetGenericTypeDefinition() == typeof (Nullable <>) cubriría eso; ¿no? –

+2

@William 'GetGenericTypeDefinition()' arroja una excepción si el tipo no es genérico. – hvd

1

¿Alló como esto? A menos que realmente necesites hacerlo de forma dinámica.

if (string.IsNullOrEmpty(input)) 
{ 
    return new DateTime?(); 
} 
else 
{ 
    return new DateTime?(DateTime.Parse(input)); 
} 

Posiblemente se puede comprobar para ver si su tipo es uno de los tipos 'anulables' y entonces tal vez usted podría encontrar algo útil aquí:

Convert string to nullable type (int, double, etc...)

+0

lo que pueda' t especifica DateTime, se determina en tiempo de ejecución. –

+0

'return new DateTime?();' Debe reemplazarse por 'return null;'. – ken2k

+0

Quizás si pudiera proporcionar más información sobre lo que está tratando de hacer en lugar de lo que está haciendo actualmente, ¿podría aconsejarle? – Paddy

9

escribí el siguiente método de ayuda genérico que funciona en la mayoría de los escenarios (no probados con tipos genéricos):

static void Main(string[] args) 
{ 
    Object result = 
     ConvertValue(
      "System.Nullable`1[[System.DateTime, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]", 
      "2012-02-23 10:00:00"); 
} 

public static Object ConvertValue(string typeInString, string value) 
{ 
    Type originalType = Type.GetType(typeInString); 

    var underlyingType = Nullable.GetUnderlyingType(originalType); 

    // if underlyingType has null value, it means the original type wasn't nullable 
    object instance = Convert.ChangeType(value, underlyingType ?? originalType); 

    return instance; 
} 
+0

Gracias. Esta es la solución más elegante y funcional. –

2
public static T GetValue<T>(string Literal, T DefaultValue) 
    { 
     if (Literal == null || Literal == "" || Literal == string.Empty) return DefaultValue; 
     IConvertible obj = Literal; 
     Type t = typeof(T); 
     Type u = Nullable.GetUnderlyingType(t); 

     if (u != null) 
     { 
      return (obj == null) ? DefaultValue : (T)Convert.ChangeType(obj, u); 
     } 
     else 
     { 
      return (T)Convert.ChangeType(obj, t); 
     } 
    } 
Cuestiones relacionadas