能否让泛型接口与带泛型方法的接口互继承以实现反序列化器注入?
直接让IMessageDeserializer和ITypedMessageDeserializer<T>互相继承不可行,因为二者的职责定位存在本质差异:前者是支持任意类型的通用反序列化器,后者是仅处理单一固定类型的专用反序列化器。强制继承会导致实现类必须违背自身职责(比如ProtoMessageSerializer无法实现通用的Deserialize<T>方法)。
为什么直接继承走不通?
1. 让ITypedMessageDeserializer<T>继承IMessageDeserializer
这种设计要求所有专用反序列化器必须实现Deserialize<TAny>通用方法,但ProtoMessageSerializer只能反序列化为ProtoResponse,无法处理其他类型,最终会被迫实现一个无法正确完成的空方法或抛出异常,违背单一职责原则。
2. 让IMessageDeserializer继承ITypedMessageDeserializer<T>
IMessageDeserializer是非泛型接口,继承泛型接口必须指定具体类型(如ITypedMessageDeserializer<object>),这会丢失原泛型方法的类型安全性;若将IMessageDeserializer改为泛型接口,则会与ITypedMessageDeserializer<T>功能重复,且JsonMessageSerializer这类通用实现无法绑定到单一类型。
可行的兼容方案
方案1:重载消息订阅者的构造函数
修改MessageSubscriber,提供针对两种反序列化器的构造函数,通过委托统一处理逻辑,无需修改原有接口:
public class MessageSubscriber<TMessage> { private readonly Func<ReadOnlyMemory<byte>, TMessage> _deserializeFunc; // 适配专用反序列化器 public MessageSubscriber(ITypedMessageDeserializer<TMessage> typedDeserializer) { _deserializeFunc = typedDeserializer.Deserialize; } // 适配通用反序列化器 public MessageSubscriber(IMessageDeserializer generalDeserializer) { _deserializeFunc = generalDeserializer.Deserialize<TMessage>; } public Task HandleMessage(ReadOnlyMemory<byte> memory) { var message = _deserializeFunc(memory); // 业务处理逻辑 } }
注入时直接传入对应的反序列化器即可,无需额外适配。
方案2:适配器模式封装通用反序列化器
实现一个适配器类,将IMessageDeserializer转换为ITypedMessageDeserializer<T>,让两种反序列化器统一到同一接口:
// 适配器扩展与实现 public static class DeserializerAdapter { public static ITypedMessageDeserializer<T> AsTyped<T>(this IMessageDeserializer deserializer) { return new TypedDeserializerAdapter<T>(deserializer); } private class TypedDeserializerAdapter<T> : ITypedMessageDeserializer<T> { private readonly IMessageDeserializer _innerDeserializer; public TypedDeserializerAdapter(IMessageDeserializer inner) { _innerDeserializer = inner; } public T Deserialize(ReadOnlyMemory<byte> memory) { return _innerDeserializer.Deserialize<T>(memory); } } }
注入时只需将JsonMessageSerializer通过AsTyped<T>()转换:
// 注入通用反序列化器的适配版本 var subscriber = new MessageSubscriber<MyMessage, ITypedMessageDeserializer<MyMessage>>( new JsonMessageSerializer().AsTyped<MyMessage>() ); // 直接注入专用反序列化器 var protoSubscriber = new MessageSubscriber<ProtoResponse, ITypedMessageDeserializer<ProtoResponse>>( new ProtoMessageSerializer() );
方案3:定义统一基础接口
新增一个基础泛型接口,让两个原有接口都继承它,统一约束:
// 基础接口 public interface IMessageDeserializerBase<T> { T Deserialize(ReadOnlyMemory<byte> memory); } // 调整原有接口 public interface ITypedMessageDeserializer<out T> : IMessageDeserializerBase<T> { } public interface IMessageDeserializer { T Deserialize<T>(ReadOnlyMemory<byte> memory); } // 给通用反序列化器添加基础接口的泛型实现 public class JsonMessageSerializer : IMessageSerializer, IMessageDeserializer, IMessageDeserializerBase<T> { // 原有实现... // 显式实现基础接口(针对任意T) T IMessageDeserializerBase<T>.Deserialize(ReadOnlyMemory<byte> memory) { return Deserialize<T>(memory); } }
此时MessageSubscriber的约束可改为IMessageDeserializerBase<TMessage>,两种反序列化器都能满足要求。
内容的提问来源于stack exchange,提问作者yenta

