이것은 예를 들어 조금 길지만 비교적 견고한 접근 방식이며 알 수없는 값에서 알 수없는 유형으로 캐스팅하는 작업을 분리합니다.
비슷한 것을 수행하고 nullable 형식을 고려하는 TryCast 메서드가 있습니다.
public static bool TryCast<T>(this object value, out T result)
{
var type = typeof (T);
// If the type is nullable and the result should be null, set a null value.
if (type.IsNullable() && (value == null || value == DBNull.Value))
{
result = default(T);
return true;
}
// Convert.ChangeType fails on Nullable<T> types. We want to try to cast to the underlying type anyway.
var underlyingType = Nullable.GetUnderlyingType(type) ?? type;
try
{
// Just one edge case you might want to handle.
if (underlyingType == typeof(Guid))
{
if (value is string)
{
value = new Guid(value as string);
}
if (value is byte[])
{
value = new Guid(value as byte[]);
}
result = (T)Convert.ChangeType(value, underlyingType);
return true;
}
result = (T)Convert.ChangeType(value, underlyingType);
return true;
}
catch (Exception ex)
{
result = default(T);
return false;
}
}
물론 TryCast는 유형 매개 변수가있는 메서드이므로 동적으로 호출하려면 MethodInfo를 직접 구성해야합니다.
var constructedMethod = typeof (ObjectExtensions)
.GetMethod("TryCast")
.MakeGenericMethod(property.PropertyType);
그런 다음 실제 속성 값을 설정하십시오.
public static void SetCastedValue<T>(this PropertyInfo property, T instance, object value)
{
if (property.DeclaringType != typeof(T))
{
throw new ArgumentException("property's declaring type must be equal to typeof(T).");
}
var constructedMethod = typeof (ObjectExtensions)
.GetMethod("TryCast")
.MakeGenericMethod(property.PropertyType);
object valueToSet = null;
var parameters = new[] {value, null};
var tryCastSucceeded = Convert.ToBoolean(constructedMethod.Invoke(null, parameters));
if (tryCastSucceeded)
{
valueToSet = parameters[1];
}
if (!property.CanAssignValue(valueToSet))
{
return;
}
property.SetValue(instance, valueToSet, null);
}
그리고 property.CanAssignValue를 다루는 확장 메소드 ...
public static bool CanAssignValue(this PropertyInfo p, object value)
{
return value == null ? p.IsNullable() : p.PropertyType.IsInstanceOfType(value);
}
public static bool IsNullable(this PropertyInfo p)
{
return p.PropertyType.IsNullable();
}
public static bool IsNullable(this Type t)
{
return !t.IsValueType || Nullable.GetUnderlyingType(t) != null;
}