2010-05-05 5 views
5

В настоящее время я работаю над приложением, в котором мне нужно загрузить данные из базы данных SQL, а затем назначить полученные значения в свойства объекта. Я делаю это, используя отражение, поскольку имена свойств и имена столбцов одинаковы. Однако многие свойства используют собственный тип структуры, который в основном представляет собой оболочку валюты для десятичного типа. Я определил неявное преобразование в моей структуре:C# неявные преобразования

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

Он бросает ArgumentException о том, что он не может конвертировать из System.Decimal в валюте. Я смущен, так как он отлично работает в любых других обстоятельствах.

ответ

3

I думаю Вам необходимо сначала удалить значение в 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); 
    } 
} 

Это вопрос, который я видел один или два раза раньше, так что я на самом деле решил write a blog post about it. Любой, кто ищет немного больше объяснений, не стесняйтесь читать.

+0

Это сработало отлично! Спасибо! –

0

Хотя я не отвечаю на вашу проблему, я думаю, что в такой ситуации было бы более целесообразно использовать ORM-структуру, такую ​​как Entity Framework или NHibernate, которая будет отображать ваши таблицы в объекты вашего домена и обрабатывать все преобразования для вы. Используя что-то вроде отражения, чтобы выяснить, какие поля для заполнения объекта домена - это медленный способ сделать это.

+1

Обычно я был бы очень обеспокоен этим, но на самом деле это не влияет на то, что я могу собрать. Это относительно небольшой набор данных (56 столбцов/свойств), поэтому добавленные накладные расходы не являются большой проблемой. Однако я ценю это предложение. –

2

Я предполагаю, что table имеет тип DataTable в коде, так что первый индексатор возвращает DataRow, а второй один возвращает object. Тогда PropertyInfo.SetValue также принимает object в качестве второго аргумента. Ни в коем случае в этом коде не происходит в коде, поэтому перегруженный оператор преобразования не применяется.

Вообще говоря, он применяется только тогда, когда известны статические типы (забыв о в C# 4.0 на данный момент). Он не применяется при боксировании и распаковке вещей. В этом случае указатель на DataRow указывает значение, а PropertyInfo.SetValue пытается распаковать его на другой тип - и не удается.

10

К сожалению, эти пользовательские операторы преобразования не используются средой выполнения; они используются компилятором только во время компиляции. Поэтому, если вы берете строго типизированный decimal и назначаете его строго типизированному Currency, компилятор будет вставлять вызов вашему оператору конверсии, и все будут счастливы. Однако, когда вы вызываете SetValue, как вы это делаете, среда выполнения ожидает, что вы дадите ей значение соответствующего типа; среда выполнения не имеет представления о том, что этот оператор преобразования существует, и никогда его не назовешь.

+2

Точно. Неявные преобразования похожи на методы расширения и параметры по умолчанию - что-то делает компилятор. – TomTom

+0

А, я вижу. Я ценю понимание, я должен уметь найти лучший способ сделать это. Спасибо :) –

Смежные вопросы