我有两个成员类型作为字符串 - 而不是类型实例.如何检查这两种类型是否可浇铸?假设字符串1是"System.Windows.Forms.Label",另一个是"System.Windows.Forms.Control".如何检查第一个是否是第二个的子类(或隐式可转换)?这是否可以通过使用反射?
感谢你的支持!
jas*_*son 17
看起来你应该使用它,Type.IsAssignableFrom但要仔细注意文档:
public virtual bool IsAssignableFrom(Type c)
trueifc和当前[instance of]Type表示相同类型,或者当前[instance of]Type是否在继承层次结构中c,或者当前[instance of]Type是c实现的接口,或者ifc是泛型类型参数和当前[instance of]Type代表其中一个约束c.false如果这些条件都不是true,或者是否c为null引用(Nothing在Visual Basic中).
特别是:
class Base { }
clase NotABase { public static implicit operator Base(NotABase o) { // } }
Console.WriteLine(typeof(Base).IsAssignableFrom(typeof(NotABase)));
Run Code Online (Sandbox Code Playgroud)
False即使NotABases可以隐式地转换为Bases,它也会在控制台上打印.所以,为了处理铸造,我们可以像这样使用反射:
static class TypeExtensions {
public static bool IsCastableTo(this Type from, Type to) {
if (to.IsAssignableFrom(from)) {
return true;
}
return from.GetMethods(BindingFlags.Public | BindingFlags.Static)
.Any(
m => m.ReturnType == to &&
(m.Name == "op_Implicit" ||
m.Name == "op_Explicit")
);
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
Console.WriteLine(typeof(string).IsCastableTo(typeof(int))); // false
Console.WriteLine(typeof(NotABase).IsCastableTo(typeof(Base))); // true
Run Code Online (Sandbox Code Playgroud)
而对于你的情况
// from is string representing type name, e.g. "System.Windows.Forms.Label"
// to is string representing type name, e.g. "System.Windows.Forms.Control"
Type fromType = Type.GetType(from);
Type toType = Type.GetType(to);
bool castable = from.IsCastableTo(to);
Run Code Online (Sandbox Code Playgroud)
我得到了这次讨论的帮助,谢谢.
我修改了nawfal的代码来解决有关原始类型的问题.
现在它返回正确的结果.
typeof(short).IsCastableTo(typeof(int)); // True
typeof(short).IsCastableTo(typeof(int), implicitly:true); // True
typeof(int).IsCastableTo(typeof(short)); // True
typeof(int).IsCastableTo(typeof(short), implicitly:true); // False
Run Code Online (Sandbox Code Playgroud)
代码如下.
public static bool IsCastableTo(this Type from, Type to, bool implicitly = false)
{
return to.IsAssignableFrom(from) || from.HasCastDefined(to, implicitly);
}
static bool HasCastDefined(this Type from, Type to, bool implicitly)
{
if ((from.IsPrimitive || from.IsEnum) && (to.IsPrimitive || to.IsEnum))
{
if (!implicitly)
return from==to || (from!=typeof(Boolean) && to!=typeof(Boolean));
Type[][] typeHierarchy = {
new Type[] { typeof(Byte), typeof(SByte), typeof(Char) },
new Type[] { typeof(Int16), typeof(UInt16) },
new Type[] { typeof(Int32), typeof(UInt32) },
new Type[] { typeof(Int64), typeof(UInt64) },
new Type[] { typeof(Single) },
new Type[] { typeof(Double) }
};
IEnumerable<Type> lowerTypes = Enumerable.Empty<Type>();
foreach (Type[] types in typeHierarchy)
{
if ( types.Any(t => t == to) )
return lowerTypes.Any(t => t == from);
lowerTypes = lowerTypes.Concat(types);
}
return false; // IntPtr, UIntPtr, Enum, Boolean
}
return IsCastDefined(to, m => m.GetParameters()[0].ParameterType, _ => from, implicitly, false)
|| IsCastDefined(from, _ => to, m => m.ReturnType, implicitly, true);
}
static bool IsCastDefined(Type type, Func<MethodInfo, Type> baseType,
Func<MethodInfo, Type> derivedType, bool implicitly, bool lookInBase)
{
var bindinFlags = BindingFlags.Public | BindingFlags.Static
| (lookInBase ? BindingFlags.FlattenHierarchy : BindingFlags.DeclaredOnly);
return type.GetMethods(bindinFlags).Any(
m => (m.Name=="op_Implicit" || (!implicitly && m.Name=="op_Explicit"))
&& baseType(m).IsAssignableFrom(derivedType(m)));
}
Run Code Online (Sandbox Code Playgroud)
如果你可以将这些字符串转换为Type对象,那么最好的选择是Type.IsAssignableFrom.
但要注意,这只会告诉您两个Type实例是否在CLR级别兼容.这不会考虑用户定义的转换或其他C#语义之类的内容.
| 归档时间: |
|
| 查看次数: |
12281 次 |
| 最近记录: |