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

如何通过依赖注入实现基于条件的IReportGenerator实例化?

问题解决:移除IReportGenerator实例化中的new关键字

问题背景

已定义IReportGenerator接口及APReportGenerator、ARReportGenerator两个实现类,原AccountController的Submit方法通过switch语句+new关键字根据ActivityReport.Type实例化对应实现类。希望移除new关键字,已在Startup.cs中注册了两个Scoped生命周期的IReportGenerator实现,但不清楚控制器如何正确获取对应实例。

解决方案

方案1:注入所有实现类并动态匹配

ASP.NET Core支持直接注入IEnumerable<IReportGenerator>,会自动将所有注册的IReportGenerator实现实例注入进来,之后可根据类型名称匹配获取对应实例。

1. 保持服务注册(或优化)

在Startup.cs中注册两个实现类:

services.AddScoped<IReportGenerator, APReportGenerator>();
services.AddScoped<IReportGenerator, ARReportGenerator>();

注:ASP.NET Core会自动收集所有注册的IReportGenerator实现,注入IEnumerable<IReportGenerator>时会包含这两个实例。

2. 修改控制器代码

注入IEnumerable<IReportGenerator>,并在Submit方法中根据Type字段匹配对应生成器:

public class AccountController : Controller
{
    private readonly IEnumerable<IReportGenerator> _reportGenerators;

    // 修正原代码中的拼写错误:AccounterController → AccountController
    public AccountController(IEnumerable<IReportGenerator> reportGenerators)
    {
        _reportGenerators = reportGenerators;
    }

    [HttpPost]
    public IActionResult Submit(ActivityReport activityReport)
    {
        // 根据Type字段匹配对应的Generator类名(如"AR"对应ARReportGenerator)
        var reportGenerator = _reportGenerators.FirstOrDefault(g => 
            g.GetType().Name.Equals($"{activityReport.Type}ReportGenerator", StringComparison.OrdinalIgnoreCase));

        if (reportGenerator == null)
        {
            return BadRequest($"不支持的报告类型:{activityReport.Type}");
        }

        reportGenerator.Process(activityReport);
        // 后续业务逻辑
        return Ok();
    }
}

方案2:使用工厂模式封装实例获取逻辑

创建专门的工厂类负责根据类型获取对应生成器,将实例化逻辑集中管理,更易维护。

1. 注册服务与工厂

在Startup.cs中注册具体实现类和工厂类:

// 注册具体的生成器实现
services.AddScoped<APReportGenerator>();
services.AddScoped<ARReportGenerator>();
// 注册工厂类
services.AddScoped<ReportGeneratorFactory>();

2. 实现工厂类

public class ReportGeneratorFactory
{
    private readonly IServiceProvider _serviceProvider;

    public ReportGeneratorFactory(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }

    public IReportGenerator GetGenerator(string reportType)
    {
        return reportType switch
        {
            "AR" => _serviceProvider.GetRequiredService<ARReportGenerator>(),
            "AP" => _serviceProvider.GetRequiredService<APReportGenerator>(),
            _ => throw new ArgumentException($"不支持的报告类型:{reportType}")
        };
    }
}

3. 修改控制器代码

注入工厂类,通过工厂获取对应生成器:

public class AccountController : Controller
{
    private readonly ReportGeneratorFactory _generatorFactory;

    public AccountController(ReportGeneratorFactory generatorFactory)
    {
        _generatorFactory = generatorFactory;
    }

    [HttpPost]
    public IActionResult Submit(ActivityReport activityReport)
    {
        try
        {
            var reportGenerator = _generatorFactory.GetGenerator(activityReport.Type);
            reportGenerator.Process(activityReport);
            // 后续业务逻辑
            return Ok();
        }
        catch (ArgumentException ex)
        {
            return BadRequest(ex.Message);
        }
    }
}

注意事项

  • 原代码中控制器构造函数存在拼写错误:AccounterController应改为AccountController,需修正。
  • 两种方案均完全移除了new关键字,依赖ASP.NET Core的DI容器管理实例生命周期,符合依赖注入原则。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 11:57:05