#c# #.net-4.0 #exception-handling
#c# #.net-4.0 #обработка исключений
Вопрос:
Я создаю произвольные объекты из потоков данных, используя отражение, и когда резина, наконец, встречается с дорогой, мне нужно взять значение из потока данных и присвоить его свойству объекта.
Поскольку потоки данных могут быть полны типов, которые не поддерживают преобразование, многие из них приводят к исключениям, которые необходимо обрабатывать. Например, DBnulls могут появляться в потоке данных или в каком-либо числовом формате, который плохо преобразуется в другой, И т. Д. Есть ли какой-либо способ избежать создания исключений? (Я не буду принимать гигантские операторы switch, проверяющие каждую комбинацию типов в свойстве целевого объекта и исходных данных.)
public void Merge(DataRow data)
{
PropertyInfo[] props = this.GetType().GetProperties(BindingFlags...);
foreach (PropertyInfo pi in props.Where(p => T_IsPrimitive(p.PropertyType)))
{
object src = null;
if( dataAsDataRow.Table.Columns.Contains(pi.Name) )
src = ((DataRow)data)[pi.Name];
if (src != null)
{
if( src.GetType() != pi.PropertyType ) {
try {
src = Convert.ChangeType(src, pi.PropertyType);
} catch(InvalidCastException e) {
try { src = Convert.ChangeType(src.ToString(), pi.PropertyType); }
catch { throw e; }
}
}
pi.SetValue(this, src, null);
}
}
}
public bool T_IsPrimitive(Type t)
{
return t.IsPrimitive || t == typeof(Decimal) || t == typeof(String) ||
t == typeof(DateTime) || t == typeof(TimeSpan)
}
Итак, есть ли какой-нибудь способ посмотреть, прежде чем я перейду к этим ChangeType
преобразованиям?
РЕШЕНИЕ
Благодаря Stecya, вот что я придумал:
if( src.GetType() != pi.PropertyType ) {
object converted = null;
TypeConverter converter = TypeDescriptor.GetConverter(pi.PropertyType);
if( converter != null ) {
if( converter.CanConvertFrom(vType) )
converted = converter.ConvertFrom(src);
else if( converter.CanConvertFrom(typeof(String)) )
converted = converter.ConvertFrom(src.ToString());
}
src = converted;
}
if( src != null )
pi.SetValue(this, src, null);
Логически эквивалентно, элегантно и больше никаких исключений!
Ответ №1:
Используйте TypeConverter, чтобы проверить, можете ли вы конвертировать между типами
bool CanConvert(Type from , Type to)
{
TypeConverter converter = TypeDescriptor.GetConverter(to);
return converter != null amp;amp; converter.CanConvertFrom(from);
}
Также вы можете использовать этот TypeConverter для фактического преобразования из одного типа в другой
Комментарии:
1. Гарантируется ли, что if
TypeDescriptor.GetConverter(Type T)
равно null или.CanConvertFrom(Type R)
равно false, а затем преобразовать. Тип изменения (T obj, тип R) завершится ошибкой? Я не хочу закрывать любые преобразования, которые могли бы быть выполнены в противном случае.2. Это должно быть, но если вы хотите быть уверены, чем использовать TypeConverter для изменения типа
Ответ №2:
Вы можете использовать шаблон посетителя. Это элегантный способ заставить функции выполнять проверку типов за вас.
Комментарии:
1. Шаблон посетителя не применяется. Как вы можете видеть, все мои преобразования относятся к псевдопримитивным типам — я не могу зайти и изменить код этих собственных типов, чтобы реализовать общий метод преобразования из типов потока данных.
2. Вы можете добавить метод расширения.