Esto es igual que Jason. responde, pero resuelve algunos problemas con su solución.
public static bool IsCastableTo(this Type from, Type to)
{
return to.IsAssignableFrom(from)
|| to.GetConvertOperators().Any(m => m.GetParameters()[0].ParameterType.IsAssignableFrom(from))
|| from.GetConvertOperators(true).Any(m => to.IsAssignableFrom(m.ReturnType));
}
public static IEnumerable<MethodInfo> GetConvertOperators(this Type type, bool lookInBase = false)
{
var bindinFlags = BindingFlags.Public
| BindingFlags.Static
| (lookInBase ? BindingFlags.FlattenHierarchy : BindingFlags.DeclaredOnly);
return type.GetMethods(bindinFlags).Where(m => m.Name == "op_Implicit" || m.Name == "op_Explicit");
}
Esto debe manejar las situaciones que surgen debido a la herencia también.Por ejemplo:
class Mammal { public static implicit operator Car (Mammal o) { return null; } }
class Cow : Mammal { }
class Vehicle { }
class Car : Vehicle { }
Aquí la relación implícita es entre Mammal
y Car
, pero desde Cow
es Mammal
así, existen una conversión implícita de Cow
a Car
. Pero todos Car
s son Vehicle
s; por lo tanto, un Cow
entraría en un Vehicle
.
Cow c = null;
Vehicle v = c; //legal
Así
typeof(Cow).IsCastableTo(typeof(Vehicle)); //true
impresiones de verdad, a pesar de que ningún operador de conversión directa existen entre Cow
y Vehicle
.
La solución anterior falla para los tipos primitivos, donde la conversión se construye directamente en el idioma que el marco, así que algo como
typeof(short).IsCastableTo(typeof(int));
falla. Afaik, solo el manejo manual lo ayudará. Obtendrá la lista completa de implicit y explicit conversión para los tipos numéricos y other primitive types de msdn.
Editar:
La función IsCastableTo
podría ser poco más "DRY", tal vez a costa de ser menos legibles, pero me gusta :)
public static bool IsCastableTo(this Type from, Type to)
{
return to.IsAssignableFrom(from)
|| IsCastDefined(to, m => m.GetParameters()[0].ParameterType, _ => from, false)
|| IsCastDefined(from, _ => to, m => m.ReturnType, true);
}
//little irrelevant DRY method
static bool IsCastDefined(Type type, Func<MethodInfo, Type> baseType, Func<MethodInfo, Type> derivedType,
bool lookInBase)
{
var bindinFlags = BindingFlags.Public
| BindingFlags.Static
| (lookInBase ? BindingFlags.FlattenHierarchy : BindingFlags.DeclaredOnly);
return type.GetMethods(bindinFlags).Any(m => (m.Name == "op_Implicit" || m.Name == "op_Explicit")
&& baseType(m).IsAssignableFrom(derivedType(m)));
}
¿De dónde vienen estas cadenas? ¿Qué está tratando de lograr? – n8wrl