Question

Je travaille actuellement sur une application où je dois charger des données à partir d'une base de données SQL et ensuite affecter les valeurs récupérées dans les propriétés d'un objet. Je fais cela en utilisant la réflexion puisque les noms de propriétés et les noms de colonnes sont les mêmes. Cependant, la plupart des propriétés utilisent un type de struct personnalisé qui est essentiellement une enveloppe de monnaie pour le type décimal. J'ai défini une conversion implicite dans mon struct:

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

Cela fonctionne bien quand je l'utilise dans le code. Cependant, quand j'ai ceci:

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

Il jette un ArgumentException indiquant qu'il ne peut pas convertir System.Decimal à la monnaie. Je suis confus car il fonctionne très bien dans toute autre circonstance.

Était-ce utile?

La solution

pense vous devez d'abord Unbox la valeur table.Rows[0][p.Name] comme decimal.

En d'autres termes:

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);
     }
}

Ceci est un problème que je l'ai vu une ou deux fois avant, donc je réellement décidé de écrire un billet de blog à ce sujet . Toute personne qui recherche un peu plus d'explications, ne hésitez pas à donner une lecture.

Autres conseils

Malheureusement, ces opérateurs de conversion définis par l'utilisateur ne sont pas utilisés par le moteur d'exécution; ils ne sont utilisés que par le compilateur au moment de la compilation. Donc, si vous prenez un decimal et l'affecter à un Currency fortement typé fortement typé, le compilateur insère un appel à votre opérateur de conversion et le plaisir de tout le monde. Cependant, lorsque vous appelez SetValue que vous faites ici, le moteur d'exécution vous attend de lui donner une valeur du type approprié; le moteur d'exécution n'a aucune idée que cet opérateur de conversion existe, et ne jamais l'appeler.

Je suppose que table est de type DataTable dans votre code, de sorte que le premier indexeur retourne un DataRow, et le second renvoie un object. Puis prend PropertyInfo.SetValue aussi un object comme second argument. A aucun endroit dans ce code un casting qui se passe dans le code , ce qui explique pourquoi l'opérateur de conversion surchargé n'est pas appliquée.

D'une manière générale, il est appliqué uniquement lorsque les types statiques sont connus (oublier dynamic en C # 4.0 pour le moment). Il est pas appliqué lorsque la boxe et les choses unboxing. Dans ce cas, l'indexeur sur les boîtes de DataRow la valeur et PropertyInfo.SetValue tente de Unbox à un type différent -. Et ne

Alors que je ne réponds pas votre problème, je pense que dans ce genre de situation, il serait plus approprié d'utiliser un cadre ORM comme Entity Framework ou NHibernate qui mapper vos tables dans vos objets de domaine et de gérer toutes les conversions pour vous . En utilisant quelque chose comme réflexion pour comprendre ce que les champs à remplir un objet de domaine est un moyen lent à le faire.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top