C#中如何优雅实现支持多过滤器的泛型RegisterPipeLine方法
提问
我有一个Mediator类,其中包含用于注册管道的泛型方法RegisterPipeLine,该方法接收消息类型、管道过滤器类型和消息处理器类型。现有实现通过重载不同泛型参数的方法支持多过滤器,但我不想为每个过滤器数量都编写重载,是否有更优雅的实现方式?
现有代码示例
单过滤器实现
internal static void RegisterPipeLine<T1, T2, T3>() where T1 : IMessage where T2 : BaseFilter where T3 : IMessageHandler { var pipeLine = new PipeLine() { Filters = [typeof(T2)], MessageHandler = typeof(T3) }; pipeLines[typeof(T1)] = pipeLine; }
调用方式:
Mediator.RegisterPipeLine<Message1, LogFilter, MessageHandler1>();
多过滤器重载实现
internal static void RegisterPipeLine<T1, T2, T3, T4>() where T1 : IMessage where T2 : BaseFilter where T3 : BaseFilter where T4 : IMessageHandler { var pipeLine = new PipeLine() { Filters = [typeof(T2), typeof(T3)], MessageHandler = typeof(T4) }; pipeLines[typeof(T1)] = pipeLine; }
调用方式:
Mediator.RegisterPipeLine<Message2, LogFilter, ValidFilter, MessageHandler2>();
回答
当然有更优雅的实现方式,以下是几种实用方案:
方案1:构建器模式(推荐,编译时安全)
这种方式支持任意数量的过滤器,链式调用直观,且能在编译时保证类型安全,完全不需要写重载:
// 定义管道构建器类 public class PipeLineBuilder<TMessage> where TMessage : IMessage { private readonly List<Type> _filters = new(); private Type _handlerType; // 添加过滤器的方法,支持链式调用 public PipeLineBuilder<TMessage> AddFilter<TFilter>() where TFilter : BaseFilter { _filters.Add(typeof(TFilter)); return this; } // 注册最终的消息处理器,完成管道注册 public void RegisterHandler<THandler>() where THandler : IMessageHandler { _handlerType = typeof(THandler); var pipeline = new PipeLine { Filters = _filters, MessageHandler = _handlerType }; Mediator.pipeLines[typeof(TMessage)] = pipeline; } } // 在Mediator类中添加创建构建器的入口方法 internal static PipeLineBuilder<TMessage> CreatePipeline<TMessage>() where TMessage : IMessage { return new PipeLineBuilder<TMessage>(); }
调用示例:
// 单过滤器场景 Mediator.CreatePipeline<Message1>() .AddFilter<LogFilter>() .RegisterHandler<MessageHandler1>(); // 多过滤器场景 Mediator.CreatePipeline<Message2>() .AddFilter<LogFilter>() .AddFilter<ValidFilter>() .RegisterHandler<MessageHandler2>();
方案2:可变泛型参数结合约束
通过调整泛型参数的顺序,把消息类型和处理器类型放在固定位置,中间用可变泛型参数接收过滤器类型:
internal static void RegisterPipeLine<TMessage, THandler, params TFilters[]>() where TMessage : IMessage where THandler : IMessageHandler where TFilters : BaseFilter { // 提取所有过滤器的类型 var filterTypes = typeof(TFilters).GetGenericArguments() .ToList(); var pipeline = new PipeLine { Filters = filterTypes, MessageHandler = typeof(THandler) }; pipeLines[typeof(TMessage)] = pipeline; }
调用示例:
// 单过滤器 Mediator.RegisterPipeLine<Message1, MessageHandler1, LogFilter>(); // 多过滤器 Mediator.RegisterPipeLine<Message2, MessageHandler2, LogFilter, ValidFilter>();
注意:这种方式依赖泛型参数的顺序,可读性略低于构建器模式,但代码量更少。
方案3:参数化传入过滤器类型
如果可以接受运行时类型校验,直接传入过滤器的Type对象是最简单的方式:
internal static void RegisterPipeLine<TMessage, THandler>(params Type[] filterTypes) where TMessage : IMessage where THandler : IMessageHandler { // 可选:运行时校验所有过滤器都继承自BaseFilter foreach (var type in filterTypes) { if (!typeof(BaseFilter).IsAssignableFrom(type)) { throw new ArgumentException($"类型 {type.Name} 不是有效的BaseFilter实现"); } } var pipeline = new PipeLine { Filters = filterTypes.ToList(), MessageHandler = typeof(THandler) }; pipeLines[typeof(TMessage)] = pipeline; }
调用示例:
// 单过滤器 Mediator.RegisterPipeLine<Message1, MessageHandler1>(typeof(LogFilter)); // 多过滤器 Mediator.RegisterPipeLine<Message2, MessageHandler2>(typeof(LogFilter), typeof(ValidFilter));
这种方式最简洁,但失去了编译时类型安全,需要额外的运行时校验逻辑。
内容的提问来源于stack exchange,提问作者David Kethel
相关产品推荐
相关产品推荐

