C # неявные преобразования
-
03-10-2019 - |
Вопрос
В настоящее время я работаю над приложением, где мне нужно загружать данные из базы данных 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, который не может преобразовать из системы. Я запутался, поскольку он отлично работает в любых других обстоятельствах.
Решение
я думать вам нужно сначала небровать значение в 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);
}
}
Это проблема, которую я видел один или два раньше, поэтому я действительно решил Написать сообщение в блоге об этом. Отказ Кто-нибудь ищет немного больше объяснений, не стесняйтесь, чтобы дать ему чтение.
Другие советы
К сожалению, эти пользовательские операторы преобразования не используются временем выполнения; Они используются только компилятором во время компиляции. Так что если вы возьмете сильно набранные decimal
и назначьте его на сильно набранный Currency
, Компилятор вставит вызов на ваш оператор преобразования и счастливых. Однако, когда вы звоните SetValue
Как вы делаете здесь, время выполнения ожидает, что вы придаете ему значение соответствующего типа; Время выполнения не имеет представления о том, что этот оператор преобразования существует, и никогда не будет называть это.
Я предполагаю что-то table
имеет тип DataTable
в вашем коде, поэтому первый индексатор возвращает DataRow
, и второй возвращает object
. Отказ потом PropertyInfo.SetValue
также берет object
как второй аргумент. В этом коде в этом коде есть в коде, Вот почему оператор перегруженного преобразования не применяется.
Вообще говоря, он применяется только тогда, когда известны статические типы (забывая о dynamic
в C # 4.0 на данный момент). Он не применяется, когда бокс и распаковки вещей. В этом случае индексатор на DataRow
коробки ценность, а PropertyInfo.SetValue
пытается UNBOX его к другому типу - и не удается.
Пока я не отвечаю на вашу проблему, я думаю, что в такой ситуации будет более целесообразным использовать рамки ORM, подобную основу для объекта или Nibernate, которые будут сопоставлять ваши таблицы в ваши доменные объекты и обрабатывать все преобразования для вас. Использование чего-то вроде отражения, чтобы выяснить, какие поля для заполнения доменного объекта - медленный способ сделать это.