Đây là một ví dụ hơi dài, nhưng đây là một cách tiếp cận tương đối mạnh mẽ và tách biệt nhiệm vụ truyền từ giá trị không xác định sang loại không xác định
Tôi có một phương thức TryCast thực hiện một cái gì đó tương tự và đưa các loại nullable vào tài khoản.
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;
}
}
Tất nhiên, TryCast là một Phương thức có Tham số Loại, vì vậy để gọi nó một cách linh hoạt, bạn phải tự xây dựng Phương thức:
var constructedMethod = typeof (ObjectExtensions)
.GetMethod("TryCast")
.MakeGenericMethod(property.PropertyType);
Sau đó, để đặt giá trị tài sản thực tế:
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);
}
Và các phương thức mở rộng để đối phó với 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;
}