C'est un peu long pour un exemple, mais c'est une approche relativement robuste, et sépare la tâche de transtypage d'une valeur inconnue en un type inconnu
J'ai une méthode TryCast qui fait quelque chose de similaire et prend en compte les types nullables.
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;
}
}
Bien sûr TryCast est une méthode avec un paramètre de type, donc pour l'appeler dynamiquement, vous devez construire vous-même le MethodInfo:
var constructedMethod = typeof (ObjectExtensions)
.GetMethod("TryCast")
.MakeGenericMethod(property.PropertyType);
Ensuite, pour définir la valeur réelle de la proprié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);
}
Et les méthodes d'extension pour gérer les propriétés.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;
}