ASP.NET Core 6 Web API:路由参数初始化服务并注入所有控制器
解决ASP.NET Core 6中通过路由参数初始化服务并注入控制器的问题
你的核心问题在于:ASP.NET Core的控制器由依赖注入容器实例化,构造函数参数需要容器能直接解析,但路由参数是请求处理阶段才会出现的动态值,无法在控制器构造时传入,所以原抽象控制器的写法行不通。以下是两种可行的解决方案:
方案一:改进抽象控制器,在动作执行前初始化服务
直接修改抽象控制器,在OnActionExecuting方法中提取路由参数并初始化MyService,这是最直接的实现方式:
[Route("api/{business}")] [ApiController] public abstract class CBaseController : ControllerBase { protected MyService? MyService { get; private set; } public override void OnActionExecuting(ActionExecutingContext context) { base.OnActionExecuting(context); // 从路由参数中解析business值 if (context.RouteData.Values.TryGetValue("business", out var businessValue) && int.TryParse(businessValue.ToString(), out var businessId)) { MyService = new SdkConnect(businessId); } else { // 参数无效时直接返回错误响应 context.Result = BadRequest("Invalid business parameter"); } } }
继承该抽象控制器的具体控制器可直接使用MyService:
[Route("api/{business}/customers")] public class CustomersController : CBaseController { [HttpGet] public IActionResult Get() { if (MyService == null) { return BadRequest(); } // 调用MyService处理业务逻辑 var customers = MyService.GetCustomers(); return Ok(customers); } }
方案二:结合工厂模式与依赖注入(推荐)
为了遵循依赖注入的设计原则,避免直接在控制器中new服务实例,可以创建服务工厂:
1. 定义工厂接口与实现
public interface IMyServiceFactory { MyService Create(int businessId); } public class MyServiceFactory : IMyServiceFactory { public MyService Create(int businessId) { return new SdkConnect(businessId); } }
2. 注册工厂到DI容器
在Program.cs中添加注册代码:
builder.Services.AddScoped<IMyServiceFactory, MyServiceFactory>();
3. 修改抽象控制器注入工厂
[Route("api/{business}")] [ApiController] public abstract class CBaseController : ControllerBase { protected MyService? MyService { get; private set; } private readonly IMyServiceFactory _serviceFactory; public CBaseController(IMyServiceFactory serviceFactory) { _serviceFactory = serviceFactory; } public override void OnActionExecuting(ActionExecutingContext context) { base.OnActionExecuting(context); if (context.RouteData.Values.TryGetValue("business", out var businessValue) && int.TryParse(businessValue.ToString(), out var businessId)) { MyService = _serviceFactory.Create(businessId); } else { context.Result = BadRequest("Invalid business parameter"); } } }
这种方式更利于单元测试,你可以轻松替换工厂的实现来模拟MyService。
内容的提问来源于stack exchange,提问作者dlogon
相关产品推荐
相关产品推荐

