2009-09-28 18 views
10

Intento establecer una propiedad Nullable <> dinámicamente.Establecer propiedad Nullable <> por reflexión

Obtengo mi propiedad por ejemplo:

PropertyInfo property = class.GetProperty("PropertyName"); // My property is Nullable<> at this time So the type could be a string or int 

Quiero configurar mi propiedad por la reflexión como

property.SetValue(class,"1256",null); 

No está funcionando cuando mi propiedad es un anulable <> genérico. Entonces trato de encontrar una manera de establecer mi propiedad.

conocer el tipo de mi anulable <> propiedad ejecuto

Nullable.GetUnderlyingType(property.PropertyType) 

Alguna idea?

  • intento crear una instancia de mi anulable <> propiedad con

    var = nullVar Activator.CreateInstance (typeof (anulable <>). MakeGenericType (nuevo tipo [] {Nullable.GetUnderlyingType (propiedad .Tipo de propiedad) }));

Pero nullVar siempre es nulo

+0

¿Funciona cuando se establece un entero en lugar de una cadena? '" 1256 "' es una cadena, no un número entero. –

+0

Funcionará, pero el punto es que no sé el tipo de propiedad que admite valores NULL. Podría usar Nullable.GetUnderlyingType (property.PropertyType) para obtener el tipo –

+0

'Nullable <>' no puede usar 'string' para el tipo subyacente ya que' string' es un tipo de referencia. En otras palabras, 'typeof (Nullable <>). MakeGenericType (t);' estará bien si 't == typeof (int)', pero explotará (restricción no cumplida) con 't == typeof (string)' . Por lo tanto, 'Nullable <>' no actuará de ninguna manera como un tipo de "tipo común" para los tipos de referencia y los tipos de valor que aceptan valores. –

Respuesta

13

Si desea convertir una cadena arbitraria al tipo subyacente de la anulable, se puede utilizar la clase Convert:

var propertyInfo = typeof(Foo).GetProperty("Bar"); 
object convertedValue = null; 
try 
{ 
    convertedValue = System.Convert.ChangeType("1256", 
     Nullable.GetUnderlyingType(propertyInfo.PropertyType)); 
} 
catch (InvalidCastException) 
{ 
    // the input string could not be converted to the target type - abort 
    return; 
} 
propertyInfo.SetValue(fooInstance, convertedValue, null); 

Este ejemplo funcionará si el tipo de destino es de tipo int, corto, largo (o variantes sin firmar, ya que la cadena de entrada representa un número no negativo), doble, flotante o decimal. Advertencia: este no es un código rápido.

+0

Voy a intentar eso, en este momento creo que eres la respuesta más cercana que busco –

+0

Está funcionando Gracias –

+0

Está trabajando gracias –

9

Si se trata de un int anulable, se tendrá que utilizar un parámetro int, no es una cadena.

property.SetValue(klass,1256,null); 

nota el cambio a Klass, en lugar de la clase, ya que la clase es una palabra clave reservada. También puede usar @class si es absolutamente necesario (citarlo).

Si su propiedad es genérica, entonces creo que probablemente necesite usar Convert para convertir lo que tenga a lo que necesite.

var nullType = Nullable.GetUnderlyingType(property.PropertyType) 
var value = Convert.ChangeType("1256", nullType); 
property.SetValue(klass, value, null); 
+0

Sé que es una cadena, pero es genérica, así que no sé cuál será el tipo. Es solo un ejemplo, mi genric Nullable <> podría ser una cadena, int. Una conversión genérica se realizará –

+2

No puede tener un 'Nullable ', ya que 'string' no es un tipo de valor. –

2

"1256" es una cadena, no un int.

5

Aquí es un ejemplo completo que muestra cómo hacerlo:

using System; 
using System.Reflection; 

class Test 
{ 
    static void Main() 
    { 
     Foo foo = new Foo(); 
     typeof(Foo).GetProperty("Bar") 
      .SetValue(foo, 1234, null); 
    } 
} 

class Foo 
{ 
    public Nullable<Int32> Bar { get; set; } 
} 

Como ya han dicho que necesita para aprobar el tipo correcto de la función SetValue pero su otro código reflexión no esta del todo bien tampoco. Debe obtener el tipo de la clase en cuestión antes de poder consultar a sus miembros.

Edit: Si entiendo correctamente, está tratando de establecer un valor de cadena a cualquier propiedad mediante reflexión. Para hacer esto, necesitará hacer una inspección de tipo y una conversión tipo.

Aquí es un ejemplo de lo que quiero decir:

using System; 
using System.Reflection; 

class Test 
{ 
    static void Main() 
    { 
     Foo foo = new Foo(); 

     PropertyInfo property = typeof(Foo).GetProperty("Bar"); 
     Object value = 
      Convert.ChangeType("1234", 
       Nullable.GetUnderlyingType(property.PropertyType) 
       ?? property.PropertyType); 

     property.SetValue(foo, value, null); 
    } 
} 

class Foo 
{ 
    public Nullable<Int32> Bar { get; set; } 
} 

Este enfoque se puede utilizar de forma segura, independientemente de si es o no la propiedad es Nullable<>.

2

Me tocó este mismo problema así como un problema con Convert.ChangeType no manejando DateTimes en Nullables así que combiné un par de soluciones stackoverflow con algo de magia dinámica .NET 4 para obtener algo que creo que es algo dulce. Si observa el código, usamos dynamic para escribir el objeto en Nullable en tiempo de ejecución, luego el tiempo de ejecución lo trata de manera diferente y permite asignaciones del tipo base al objeto que admite nulos.

public void GenericMapField(object targetObj, string fieldName, object fieldValue) 
{ 
    PropertyInfo prop = targetObj.GetType().GetProperty(fieldName); 
    if (prop != null) 
    { 
     if (prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>)) 
     { 
      dynamic objValue = System.Activator.CreateInstance(prop.PropertyType); 
      objValue = fieldValue; 
      prop.SetValue(targetObj, (object)objValue, null); 
     } 
     else 
     { 
      prop.SetValue(targetObj, fieldValue, null); 
     } 
    } 
} 
0
public static void SetValue(object target, string propertyName, object value) 
{ 
    if (target == null) 
    return; 

    PropertyInfo propertyInfo = target.GetType().GetProperty(propertyName); 

    object convertedValue = value; 
    if (value != null && value.GetType() != propertyInfo.PropertyType) 
    { 
    Type propertyType = Nullable.GetUnderlyingType(propertyInfo.PropertyType) ?? propertyInfo.PropertyType; 
    convertedValue = Convert.ChangeType(value, propertyType); 
    } 

    propertyInfo.SetValue(target, convertedValue, null); 
} 
Cuestiones relacionadas