如何判断并断言System.Type实现接口及new()约束以调用对应反序列化方法
解决方案
问题1:检查类型是否满足new()约束
new()约束的核心要求是类型拥有公共无参构造函数,可以通过反射直接检查:
bool hasPublicParameterlessCtor = typeof(T).GetConstructor( BindingFlags.Public | BindingFlags.Instance, Type.EmptyTypes) != null;
必须指定BindingFlags,避免误识别非公共的无参构造函数。
问题2:运行时断言约束并调用DeserializeSpecial<T>
编译器在编译阶段无法识别你做的运行时类型检查,直接调用DeserializeSpecial<T>会触发约束不满足的错误。可以通过反射调用泛型方法或动态类型解析解决,以下是两种可行方案:
方案1:反射调用(可控性强)
using System; using System.Reflection; public static class Deserializer { // 已实现的普通反序列化方法 public static T DeserializeNormal<T>(string s) { // 普通反序列化逻辑 return default(T); } // 已实现的特殊反序列化方法 public static T DeserializeSpecial<T>(string s) where T : IMessage<T>, new() { // 特殊反序列化逻辑 return new T(); } // 通用入口方法 public static T Deserialize<T>(string s) { Type tType = typeof(T); // 检查是否实现IMessage<T> Type iMessageType = typeof(IMessage<>).MakeGenericType(tType); bool isIMessageImpl = iMessageType.IsAssignableFrom(tType); // 检查是否满足new()约束 bool hasValidCtor = tType.GetConstructor( BindingFlags.Public | BindingFlags.Instance, Type.EmptyTypes) != null; if (isIMessageImpl && hasValidCtor) { // 反射构造并调用DeserializeSpecial<T> MethodInfo specialMethod = typeof(Deserializer) .GetMethod(nameof(DeserializeSpecial)) .MakeGenericMethod(tType); return (T)specialMethod.Invoke(null, new object[] { s }); } else { return DeserializeNormal<T>(s); } } } // 示例接口定义 public interface IMessage<T> { }
方案2:Dynamic简化调用(代码更简洁)
利用dynamic的运行时类型解析绕过编译检查:
public static T Deserialize<T>(string s) { Type tType = typeof(T); Type iMessageType = typeof(IMessage<>).MakeGenericType(tType); bool isIMessageImpl = iMessageType.IsAssignableFrom(tType); bool hasValidCtor = tType.GetConstructor( BindingFlags.Public | BindingFlags.Instance, Type.EmptyTypes) != null; if (isIMessageImpl && hasValidCtor) { // 通过dynamic让运行时匹配泛型约束 return DeserializeSpecialWrapper((dynamic)s, default(T)); } else { return DeserializeNormal<T>(s); } } // 辅助包装方法,用于触发泛型约束检查 private static T DeserializeSpecialWrapper<T>(string s, T _) where T : IMessage<T>, new() { return DeserializeSpecial<T>(s); }
内容的提问来源于stack exchange,提问作者riizade
相关产品推荐
相关产品推荐

