2010-05-05 21 views
5

Actualmente estoy trabajando en una aplicación en la que necesito cargar datos de una base de datos SQL y luego asignar los valores recuperados a las propiedades de un objeto. Lo hago utilizando la reflexión ya que los nombres de las propiedades y los nombres de las columnas son los mismos. Sin embargo, muchas de las propiedades están usando un tipo de estructura personalizada que básicamente es un contenedor de moneda para el tipo decimal. He definido una conversión implícita en mi estructura:C# conversiones implícitas

public static implicit operator Currency(decimal d) 
{ 
    return new Currency(d); 
} 

Esto funciona bien cuando lo uso en el código. Sin embargo, cuando tengo esto:

foreach (PropertyInfo p in props) 
{ 
    p.SetValue(this, table.Rows[0][p.Name], null); 
} 

Se lanza una excepción ArgumentException que indica que no se puede convertir de System.Decimal de divisas. Estoy confundido ya que funciona bien en cualquier otra circunstancia.

Respuesta

3

I piensa primero necesita destrabar el valor en table.Rows[0][p.Name] como decimal.

En otras palabras:

foreach (PropertyInfo p in props) 
{ 
    if (p.PropertyType == typeof(Currency)) 
    { 
     Currency c = (decimal)table.Rows[0][p.Name]; 
     p.SetValue(this, c, null); 
    } 
    else 
    { 
     p.SetValue(this, table.Rows[0][p.Name], null); 
    } 
} 

Este es un tema que he visto una o dos veces antes, lo que en realidad decidió write a blog post about it. Cualquiera que busque un poco más de explicación, no dude en darle una lectura.

+0

¡Esto funcionó de manera excelente! ¡Gracias! –

0

Si bien no estoy respondiendo su problema, creo que en este tipo de situación sería más apropiado usar un marco ORM como Entity Framework o NHibernate que mapeará sus tablas en sus objetos de dominio y manejar todas las conversiones para tú. Usar algo como la reflexión para descubrir qué campos rellenar un objeto de dominio es una forma lenta de hacerlo.

+1

Normalmente estaría bastante preocupado por eso, pero en realidad no me afecta por lo que puedo deducir. Es un conjunto relativamente pequeño de datos (56 columnas/propiedades) por lo que la sobrecarga adicional no es un gran problema. Aunque aprecio la sugerencia. –

2

que asumen que table es de tipo DataTable en su código, por lo que el primer paso a paso devuelve un DataRow, y el segundo devuelve un object. Entonces PropertyInfo.SetValue también toma un object como el segundo argumento. En ningún lugar de este código, se produce un lanzamiento en el código, por lo que no se aplica el operador de conversión sobrecargado.

En general, solo se aplica cuando se conocen tipos estáticos (olvidando dynamic en C# 4.0 por el momento). No se aplica cuando boxeo y desempaquetar cosas. En este caso, el indexador en DataRow incluye el valor en el cuadro y PropertyInfo.SetValue intenta desvincularlo a un tipo diferente y falla.

10

Desafortunadamente, estos operadores de conversión definidos por el usuario no son utilizados por el tiempo de ejecución; solo los usa el compilador en el momento de la compilación. Por lo tanto, si toma un decimal fuertemente tipado y lo asigna a un Currency fuertemente tipado, el compilador insertará una llamada a su operador de conversión y todo el mundo estará contento. Sin embargo, cuando llame al SetValue como lo hace aquí, el tiempo de ejecución espera que le dé un valor del tipo apropiado; el tiempo de ejecución no tiene idea de que este operador de conversión existe, y nunca lo llamará.

+2

Exactamente. Las conversiones implícitas son similares a los métodos de extensión y los parámetros predeterminados, algo que hace el compilador. – TomTom

+0

Ah, ya veo. Aprecio la comprensión, debería ser capaz de encontrar una mejor manera de hacer esto. Gracias :) –

Cuestiones relacionadas