You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

支持多方法处理请求的C#/OOP解耦架构方案咨询

C# 场景下请求多处理者解耦架构实现方案

核心需求的本质是让请求发起方和处理方完全无直接依赖,处理逻辑按构建版本自动路由,最适配的实现是抽象契约层+轻量中介分发+依赖注入装配的组合,完全符合OOP设计原则,落地代码如下:

核心实现步骤

  • 第一步:抽离最薄公共契约层
    把请求、处理者、分发器的抽象单独放在无业务依赖的契约项目里,所有业务模块都只依赖这层抽象,不依赖其他业务模块的具体实现:
    // 所有业务请求的标记接口,无任何方法约束
    public interface IRequest { }
    
    // 请求处理者泛型抽象,约束请求类型必须实现IRequest
    public interface IRequestHandler<in TRequest> where TRequest : IRequest
    {
        Task HandleAsync(TRequest request, CancellationToken ct = default);
    }
    
    // 请求分发器抽象,发起方只依赖这个接口发送请求
    public interface IRequestDispatcher
    {
        Task SendAsync<TRequest>(TRequest request, CancellationToken ct = default) where TRequest : IRequest;
    }
    
  • 第二步:各模块独立实现业务逻辑
    请求发起方(类A)、不同版本的处理方(类B、类C)分别在各自的模块里实现逻辑,互相之间没有任何项目引用、代码依赖:
    // 具体业务请求,只携带操作需要的参数,不耦合任何处理逻辑
    public record OperationRequest(int BizId, string BizContent) : IRequest;
    
    // 发起请求的类A,只依赖分发器抽象,完全不知道类B、类C的存在
    public class ClassA
    {
        private readonly IRequestDispatcher _dispatcher;
        // 构造函数注入分发器实例,不接触任何具体处理类
        public ClassA(IRequestDispatcher dispatcher) => _dispatcher = dispatcher;
    
        public async Task RunOperation()
        {
            var req = new OperationRequest(1001, "业务参数");
            // 直接发送请求即可,不需要关心谁来处理、怎么处理
            await _dispatcher.SendAsync(req);
        }
    }
    
    // V1版本处理逻辑类B,只依赖契约层和自己的业务依赖,和类A无直接关联
    public class ClassB : IRequestHandler<OperationRequest>
    {
        public async Task HandleAsync(OperationRequest request, CancellationToken ct)
        {
            // V1版本的具体处理逻辑
            Console.WriteLine($"V1逻辑处理请求,业务ID:{request.BizId}");
            await Task.CompletedTask;
        }
    }
    
    // V2版本处理逻辑类C,和类A、类B都无直接依赖
    public class ClassC : IRequestHandler<OperationRequest>
    {
        public async Task HandleAsync(OperationRequest request, CancellationToken ct)
        {
            // V2版本的具体处理逻辑
            Console.WriteLine($"V2逻辑处理请求,业务ID:{request.BizId}");
            await Task.CompletedTask;
        }
    }
    
  • 第三步:实现版本感知的分发逻辑
    分发器是唯一持有路由规则的组件,负责根据当前构建版本匹配对应的处理者执行,路由逻辑完全集中在这里,业务层无感知:
    public class VersionBasedDispatcher : IRequestDispatcher
    {
        private readonly IServiceProvider _sp;
        // 当前程序的构建版本,可从编译常量、程序集版本、环境配置读取
        private readonly int _currentVersion = ResolveCurrentVersion();
    
        public VersionBasedDispatcher(IServiceProvider sp) => _sp = sp;
    
        public async Task SendAsync<TRequest>(TRequest request, CancellationToken ct) where TRequest : IRequest
        {
            // 按版本路由到对应处理者:V1走类B,V2及以上走类C
            IRequestHandler<TRequest> handler = _currentVersion switch
            {
                1 => (IRequestHandler<TRequest>)_sp.GetRequiredService(typeof(ClassB)),
                >=2 => (IRequestHandler<TRequest>)_sp.GetRequiredService(typeof(ClassC)),
                _ => throw new NotSupportedException($"版本{_currentVersion}无对应处理实现")
            };
            await handler.HandleAsync(request, ct);
        }
    
        private static int ResolveCurrentVersion()
        {
            // 示例用编译宏判断版本,可根据自己的构建流程替换读取逻辑
    #if BUILD_V1
            return 1;
    #elif BUILD_V2
            return 2;
    #else
            return 1;
    #endif
        }
    }
    
  • 第四步:启动层统一装配依赖
    在程序启动入口的DI注册阶段完成所有依赖绑定,这是唯一同时引用契约层、类A、类B、类C所在模块的地方:
    // .NET 控制台/ASP.NET Core 服务注册示例
    var services = new ServiceCollection();
    services.AddScoped<IRequestDispatcher, VersionBasedDispatcher>();
    services.AddScoped<ClassB>();
    services.AddScoped<ClassC>();
    services.AddScoped<ClassA>();
    
    var serviceProvider = services.BuildServiceProvider();
    // 调用示例,实际业务中不需要手动获取ClassA,由DI自动注入
    var aInstance = serviceProvider.GetRequiredService<ClassA>();
    await aInstance.RunOperation();
    

方案特性

  • 解耦彻底:类A所在的项目不需要引用类B、类C的程序集,B、C的逻辑修改、新增/删除处理类都不会导致A重新编译,完全符合要求
  • 扩展灵活:后续要加AB测试分流、多租户差异化处理、灰度发布规则,只需要修改分发器的路由逻辑,业务代码零改动
  • 符合开闭原则:新增处理逻辑只需要新增对应的处理类,不需要修改已有业务代码

不想自己实现分发逻辑的话,直接用MediatR即可,它已经封装了完整的请求分发能力,只需要在DI注册阶段按当前构建版本注册对应请求的处理实现即可,核心原理和上述实现完全一致。

内容的提问来源于stack exchange,提问作者mhdnt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 10:42:22