泛型类参数化后的基类问题
泛型只是一种代码实现技术,在编译的过程中,会根据泛型的参数类型,生成一个对于的类。比如 :
public abstract class PacketHandler<T> : IHandler
{
public abstract string Identity();
public virtual string HandlerKey()
{
return Identity();
}
public abstract void Handler(object sender, T packet);
/// <summary>
/// 委托调用,将包转换成具体的子类。
/// </summary>
/// <param name="sender"></param>
/// <param name="packet"></param>
public void Delegate(object sender, EventArgs packet)
{
if (packet is T t)
{
Handler(sender, t);
return;
}
Debug.WriteLine($"not match packet type: {typeof(T).Name}");
}
}
public class HelloPacketHandler: PacketHandler<HelloPacket>
{
public override string Identity()
{
return PacketHandlerName.Hello;
}
public override void Handler(object sender, HelloPacket packet)
{
Console.WriteLine(nameof(HelloPacketHandler));
}
}
断点查看 HelloPacketHandler
的 BaseType
:
判断 HelloPacketHandler
类是否为 PacketHandler
泛型类参数实例化的类,不能直接用 :
// HelloPacket extends Packet
typeof(HelloPacketHandler) == typeof(PacketHandler<Packet>)
判断运行类和泛型类的关系
public class TypeUtils
{
/// <summary>
/// 判断A类是否为B类的直接派生类或者A类是否为B泛型类的直接派生类。
/// </summary>
/// <param name="aChildBaseClassType"></param>
/// <param name="bParentClass"></param>
/// <returns></returns>
public static bool isBaseTypeOfClass(Type aChildBaseClassType, Type bParentClass)
{
if (bParentClass.GenericTypeArguments.Length != aChildBaseClassType.GenericTypeArguments.Length)
{
return false;
}
if (bParentClass.GenericTypeArguments.Length == 0)
{
return aChildBaseClassType == bParentClass;
}
for (int i = 0; i < bParentClass.GenericTypeArguments.Length; i++)
{
if (!isBaseTypeOfClass(aChildBaseClassType.GenericTypeArguments[i].BaseType, bParentClass.GenericTypeArguments[i]))
{
return false;
}
}
return true;
}
}
代码测试
[Test]
public void TestIsBaseTypeOfClass()
{
Assert.True(TypeUtils.isBaseTypeOfClass(typeof(HelloPacketHandler).BaseType, typeof(PacketHandler<Packet>)));
Assert.False(TypeUtils.isBaseTypeOfClass(typeof(ChildHelloPacketHandler).BaseType, typeof(PacketHandler<Packet>)));
Assert.True(TypeUtils.isBaseTypeOfClass(typeof(ChildHelloPacketHandler).BaseType, typeof(HelloPacketHandler)));
Assert.False(TypeUtils.isBaseTypeOfClass(typeof(HelloPacketHandler).BaseType, typeof(PacketHandler<EventArgs>)));
}
测试代码下载
PacketExample,提取码:r4zv
[1] 创建单元测试