質問
現在、SQLデータベースからデータをロードし、取得した値をオブジェクトのプロパティに割り当てる必要があるアプリケーションに取り組んでいます。プロパティ名と列名は同じであるため、私はこれを反映して使用しています。ただし、プロパティの多くは、基本的に小数型の通貨ラッパーであるカスタム構造タイプを使用しています。私は自分の構造体で暗黙の変換を定義しました:
public static implicit operator Currency(decimal d)
{
return new Currency(d);
}
これは、コードで使用するときに正常に機能します。しかし、私がこれを持っているとき:
foreach (PropertyInfo p in props)
{
p.SetValue(this, table.Rows[0][p.Name], null);
}
system.decimalから通貨に変換できないことを示すargumpexceptionを投げます。他の状況ではうまく機能するので、私は混乱しています。
解決
私 考える 最初に値のボックスを解除する必要があります table.Rows[0][p.Name]
として decimal
.
言い換えると:
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);
}
}
これは私が以前に1回または2回見た問題なので、実際に決めました それについてのブログ投稿を書いてください. 。もう少し説明をお探しの方は、お気軽に読んでください。
他のヒント
残念ながら、これらのユーザー定義の変換演算子は、ランタイムでは使用されません。コンパイル時にコンパイラによってのみ使用されます。したがって、あなたが強くタイプをとるなら decimal
そして、それを強くタイプに割り当てます Currency
, 、コンパイラはあなたの変換オペレーターへの電話を挿入し、みんなは幸せです。ただし、電話するとき SetValue
ここでやっているように、ランタイムは適切なタイプの値を与えることを期待しています。ランタイムは、この変換演算子が存在することを知りません。
私はそれを想定しています table
タイプです DataTable
あなたのコードでは、最初のインデクサーが DataRow
, 、そして2番目のものが返されます object
. 。それで PropertyInfo.SetValue
もかかります object
2番目の議論として。このコードの場所では、キャストが発生しません コードで, 、これが、過負荷の変換演算子が適用されない理由です。
一般的に言えば、静的タイプがわかっている場合にのみ適用されます(忘れて dynamic
現時点でC#4.0)。ボクシングとボクシングを解除するときは、適用されません。この場合、インデクサーはオンです DataRow
値をボックス、そして PropertyInfo.SetValue
別のタイプに箱を開けようとし、失敗します。
私はあなたの問題に答えていませんが、この種の状況では、あなたのテーブルをドメインオブジェクトにマッピングし、あなたのためのすべての変換を処理するエンティティフレームワークやnhibernateなどのORMフレームワークを使用する方が適切だと思います。リフレクションのようなものを使用して、ドメインオブジェクトにどのフィールドを入力するかを把握することは、それを行うのに遅い方法です。