2010-05-05 15 views
5

Ich arbeite gerade an einer Anwendung, wo ich Daten aus einer SQL-Datenbank laden muss und dann die abgerufenen Werte den Eigenschaften eines Objekts zuweisen. Ich mache das mit Reflektion, da die Eigenschaftsnamen und die Spaltennamen identisch sind. Viele der Eigenschaften verwenden jedoch einen benutzerdefinierten Strukturtyp, der im Grunde ein Währungsumbruch für den Dezimaltyp ist. Ich habe eine implizite Konvertierung in meiner Struktur definiert:C# implizite Konvertierungen

Dies funktioniert gut, wenn ich es in Code verwenden. Allerdings, wenn ich dies:

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

Es wirft ein Argument besagt, dass es nicht von System.Decimal bis Währung umwandeln kann. Ich bin verwirrt, da es in anderen Umständen gut funktioniert.

Antwort

3

ich denken Sie den Wert in table.Rows[0][p.Name] als decimal zum ersten unbox benötigen.

Mit anderen Worten:

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

Dies ist ein Problem, das ich ein- oder zweimal zuvor gesehen haben, so entschied ich mich tatsächlich zu write a blog post about it. Wer etwas mehr Erklärungen sucht, kann es gerne lesen.

+0

Das hat hervorragend funktioniert! Vielen Dank! –

0

Während ich nicht auf Ihr Problem antworte, denke ich, dass in einer solchen Situation ein ORM Framework wie das Entity Framework oder NHibernate sinnvoller ist, das Ihre Tabellen in Ihre Domänenobjekte abbildet und alle Konvertierungen für Sie. Wenn Sie etwas wie Reflektion verwenden, um herauszufinden, welche Felder ein Domänenobjekt ausfüllen soll, ist dies ein langsamer Weg.

+1

Normalerweise wäre ich ziemlich besorgt darüber, aber es beeinflusst es nicht wirklich von dem, was ich sammeln kann. Es ist ein relativ kleiner Satz von Daten (56 Spalten/Eigenschaften), so dass der zusätzliche Overhead kein großes Problem darstellt. Ich schätze den Vorschlag jedoch. –

2

Ich gehe davon aus, dass table vom Typ DataTable in Ihrem Code, so dass der erste Indexer eine DataRow zurückkehrt, und die zweite gibt einen object. Dann nimmt PropertyInfo.SetValue auch ein object als zweites Argument. An keiner Stelle in diesem Code passiert im Code, weshalb der überladene Konvertierungsoperator nicht angewendet wird.

Im Allgemeinen wird es nur angewendet, wenn statische Typen bekannt sind (vergessen Sie in C# 4.0 im Moment dynamic). Es wird nicht beim Boxen und Unboxing angewendet. In diesem Fall boxt der Indexer auf DataRow den Wert und PropertyInfo.SetValue versucht, es auf einen anderen Typ zu entpacken - und schlägt fehl.

10

Leider werden diese benutzerdefinierten Konvertierungsoperatoren nicht von der Laufzeit verwendet; Sie werden nur vom Compiler zur Kompilierzeit verwendet. Wenn Sie also ein stark typisiertes decimal nehmen und es einem stark typisierten Currency zuweisen, fügt der Compiler einen Aufruf an Ihren Konvertierungsoperator ein, und jeder freut sich. Wenn Sie jedoch wie hier bei SetValue anrufen, erwartet die Laufzeitumgebung, dass Sie einen Wert des entsprechenden Typs angeben. Die Laufzeitumgebung hat keine Ahnung, dass dieser Konvertierungsoperator existiert und wird ihn niemals aufrufen.

+2

Genau. Implizite Conversions ähneln Extension-Methoden und Standardparametern - etwas, das der Compiler tut. – TomTom

+0

Ah, ich verstehe. Ich schätze die Einsicht, ich sollte in der Lage sein, einen besseren Weg zu finden, dies zu tun. Danke :) –

Verwandte Themen