C# неявные преобразования

Я в настоящее время работаю над приложением, где я должен загрузить данные из базы данных 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);
}

Это бросает ArgumentException, указывая, что это не может преобразовать из Системы. Десятичное число к Валюте. Я смущен, так как это хорошо работает при любом другом обстоятельстве.

5
задан Chris Boden 5 May 2010 в 19:22
поделиться

4 ответа

Я думаю, что вам нужно сначала раскрыть значение в table.Rows[0][p.Name] как десятичную дробь.

Другими словами:

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

Эту проблему я встречал один или два раза раньше, поэтому я решил написать об этом статью в блоге. Если кому-то нужно немного больше объяснений, не стесняйтесь, прочитайте.

3
ответ дан 18 December 2019 в 11:54
поделиться

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

10
ответ дан 18 December 2019 в 11:54
поделиться

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

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

2
ответ дан 18 December 2019 в 11:54
поделиться

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

0
ответ дан 18 December 2019 в 11:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: