C # неявные преобразования - PullRequest
5 голосов
/ 05 мая 2010

В настоящее время я работаю над приложением, в котором мне нужно загрузить данные из базы данных 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, заявляющее, что не может преобразовать из System.Decimal в Currency. Я в замешательстве, так как он отлично работает при любых других обстоятельствах.

Ответы [ 4 ]

10 голосов
/ 05 мая 2010

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

3 голосов
/ 05 мая 2010

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

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

2 голосов
/ 05 мая 2010

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

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

0 голосов
/ 05 мая 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...