public void CanConvertFrom() { NullableConverter converter = new NullableConverter(typeof(MyType?)); Assert.IsTrue(converter.CanConvertFrom(null, typeof(MyType)), "#1"); Assert.IsFalse(converter.CanConvertFrom(null, typeof(object)), "#2"); }
internal virtual T GetValue <T> (object target) { var converted = default(T); object value = null; bool canConvert = false; try { value = PropertyDescriptor.GetValue(PropertyProvider); var currentType = typeof(T); var underlyingType = Nullable.GetUnderlyingType(currentType); //proppy has some editors based in nullable types if (underlyingType != null) { var converterNullable = new NullableConverter(currentType); if (converterNullable.CanConvertFrom(underlyingType)) { object notNullableValue = Convert.ChangeType(value, underlyingType); return((T)converterNullable.ConvertFrom(notNullableValue)); } } var tc = PropertyDescriptor.Converter; canConvert = tc.CanConvertTo(currentType); if (canConvert) { converted = (T)tc.ConvertTo(value, currentType); } else { converted = (T)Convert.ChangeType(value, currentType); } } catch (Exception ex) { LogInternalError($"Error trying to get and convert value:'{value}' canconvert: {canConvert} T:{typeof (T).FullName} ", ex); } return(converted); }
/// <summary> /// Tries to read a column value from a data reader and return the typed value. /// </summary> /// <remarks>If the specified column is not found or the types do not match, returns default value.</remarks> /// <typeparam name="TField">The type of the field that we are reading.</typeparam> /// <param name="reader">The data reader that should contain the column value.</param> /// <param name="name">The name of the column to read.</param> /// <returns>A value of type TField.</returns> public static TField Get <TField>(this DbDataReader reader, string name) { var value = reader[name]; // check for null and return default if (value == null || value == DBNull.Value) { return(default(TField)); } // direct cast if we can... var returnType = typeof(TField); if (value.GetType() == returnType) { return((TField)value); } // nullable types require different container if (returnType.IsGenericType && returnType.GetGenericTypeDefinition() == typeof(Nullable <>)) { var converter = new NullableConverter(returnType); if (converter.CanConvertFrom(value.GetType())) { return((TField)converter.ConvertFrom(value)); } } else { return((TField)Convert.ChangeType(value, typeof(TField))); } // We tried...we failed... throw new InvalidOperationException( $"Unable to convert from database field ({value.GetType().FullName}) to object ({returnType.FullName})"); }
/// <summary> /// 将动态类型转为指定类型实体 /// </summary> /// <param name="data"></param> /// <param name="type"></param> /// <returns></returns> private static object DynamicToEntity(ExpandoObject data, Type type) { var entity = Activator.CreateInstance(type); var dic = data as IDictionary <string, object>; foreach (var item in dic) { if (item.Value == null) { continue; } var type_value = item.Value.GetType(); if (type_value == typeof(DBNull)) { continue; } var prop = type.GetProperty(item.Key, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public | BindingFlags.Static); if (prop == null) { continue; } object value = item.Value; if (type_value != prop.PropertyType) { if (type_value == typeof(List <object>)) { var valueList = Activator.CreateInstance(prop.PropertyType); var dicValueList = value as List <object>; foreach (var valueItem in dicValueList) { prop.PropertyType.GetMethod("Add") .Invoke(valueList, new object[] { DynamicToEntity(valueItem as ExpandoObject, prop.PropertyType.GenericTypeArguments[0]) }); } value = valueList; } else if (type_value == typeof(ExpandoObject)) { value = DynamicToEntity(item.Value as ExpandoObject, prop.PropertyType); } else if (prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition().Equals(typeof(Nullable <>))) { NullableConverter newNullableConverter = new NullableConverter(prop.PropertyType); try { if (!newNullableConverter.CanConvertFrom(item.Value.GetType())) { value = Convert.ChangeType(item.Value, newNullableConverter.UnderlyingType); } else { value = newNullableConverter.ConvertFrom(item.Value); } } #pragma warning disable CA1031 // Do not catch general exception types catch { value = newNullableConverter.ConvertFromString(item.Value?.ToString()); } #pragma warning restore CA1031 // Do not catch general exception types } else { value = Convert.ChangeType(item.Value, prop.PropertyType); } } prop.SetValue(entity, value); } return(entity); }