by Nicolás Ferreira
13. January 2008 00:00
Recientemente me encontré con un código que utilizando Reflection establecía valores a las propiedades de un objeto. El valor que iba a establecer en la propiedad tenía como tipo de dato String y la propiedad podía llegar a tener otro, entonces, utilizaba Convert.ChangeType cuando el tipo de dato de la propiedad era diferente a String:
class Persona
{
int _Edad;
public int Edad
{
get { return _Edad; }
set { _Edad = value; }
}
string _Nombre;
public string Nombre
{
get { return _Nombre; }
set { _Nombre = value; }
}
string _Apellido;
public string Apellido
{
get { return _Apellido; }
set { _Apellido = value; }
}
Nullable<int> _CantidadHijos;
public Nullable<int> CantidadHijos
{
get { return _CantidadHijos; }
set { _CantidadHijos = value; }
}
Nullable<int> _CantidadHermanos;
public Nullable<int> CantidadHermanos
{
get { return _CantidadHermanos; }
set { _CantidadHermanos = value; }
}
}
static void Main(string[] args)
{
StringDictionary lDiccionarioPropiedadesValores = new StringDictionary();
lDiccionarioPropiedadesValores.Add("Edad", "18");
lDiccionarioPropiedadesValores.Add("Nombre", "Nicolás");
lDiccionarioPropiedadesValores.Add("Apellido", "Ferreira");
lDiccionarioPropiedadesValores.Add("CantidadHijos", "");
lDiccionarioPropiedadesValores.Add("CantidadHermanos", "2");
Persona lPersona = new Persona();
foreach (DictionaryEntry lEntradaDiccionario in lDiccionarioPropiedadesValores)
{
PropertyInfo lPropiedadPersona = lPersona.GetType().GetProperty(lEntradaDiccionario.Key.ToString(), System.Reflection.BindingFlags.IgnoreCase | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
if (lPropiedadPersona != null)
{
object lNuevoValorPropiedad = lEntradaDiccionario.Value;
if ((lNuevoValorPropiedad != null) && (lPropiedadPersona.PropertyType != lEntradaDiccionario.Value.GetType()))
{
lNuevoValorPropiedad = Convert.ChangeType(lNuevoValorPropiedad, lPropiedadPersona.PropertyType);
}
lPropiedadPersona.SetValue(lPersona, lNuevoValorPropiedad, null);
}
}
}
El problema al correr este código es que cuando la propiedad tiene como tipo de dato a Nullable, el método Convert.ChangeType falla. La solución puede ser la siguiente:
static void Main(string[] args)
{
StringDictionary lDiccionarioPropiedadesValores = new StringDictionary();
lDiccionarioPropiedadesValores.Add("Edad", "18");
lDiccionarioPropiedadesValores.Add("Nombre", "Nicolás");
lDiccionarioPropiedadesValores.Add("Apellido", "Ferreira");
lDiccionarioPropiedadesValores.Add("CantidadHijos", "");
lDiccionarioPropiedadesValores.Add("CantidadHermanos", "2");
Persona lPersona = new Persona();
foreach (DictionaryEntry lEntradaDiccionario in lDiccionarioPropiedadesValores)
{
PropertyInfo lPropiedadPersona = lPersona.GetType().GetProperty(lEntradaDiccionario.Key.ToString(), System.Reflection.BindingFlags.IgnoreCase | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
if (lPropiedadPersona != null)
{
object lNuevoValorPropiedad = lEntradaDiccionario.Value;
if ((lNuevoValorPropiedad != null) && (lPropiedadPersona.PropertyType != lEntradaDiccionario.Value.GetType()))
{
if ((lPropiedadPersona.PropertyType.IsGenericType) && (lPropiedadPersona.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>)))
{
if (string.IsNullOrEmpty(lNuevoValorPropiedad.ToString()))
{
lNuevoValorPropiedad = null;
}
else
{
lNuevoValorPropiedad = Convert.ChangeType(lNuevoValorPropiedad, new NullableConverter(lPropiedadPersona.PropertyType).UnderlyingType);
}
}
else
{
lNuevoValorPropiedad = Convert.ChangeType(lNuevoValorPropiedad, lPropiedadPersona.PropertyType);
}
}
lPropiedadPersona.SetValue(lPersona, lNuevoValorPropiedad, null);
}
}
}
El trabajo lo hace la clase NullableConverter, lo otro es simplemente validación.