.NET Core中不通过构造函数注入获取已注入服务实例的方法
非构造注入获取
IFw_UsersRepository实例的实现方案 你当前的场景下,不需要在构造函数注入IFw_UsersRepository即可获取实例,有以下3种可落地的实现方式:
方案1:通过DI容器按需解析(推荐)
这是最符合.NET依赖注入规范的非构造注入方案,不会破坏DI的生命周期管理:
- 首先在Program.cs中注册HttpContext访问器:
builder.Services.AddHttpContextAccessor(); - 仅在构造函数中注入
IHttpContextAccessor,在需要用到仓储的方法内部,通过当前请求的服务容器按需解析实例即可,修改后的代码如下:public class WorkingCredential { private readonly IHttpContextAccessor _httpContextAccessor; public WorkingCredential(dynamic me, IHttpContextAccessor httpContextAccessor) { UserId = me.UserId; _httpContextAccessor = httpContextAccessor; } public WorkingCredential() { } public string UserId { get; set; } public bool IsInRole(string _ruleName) { // 方法执行时按需解析仓储实例 var userRepository = _httpContextAccessor?.HttpContext?.RequestServices .GetService<IFw_UsersRepository>(); if (userRepository == null) return false; var userRoles = userRepository.GetUserRolls(); // 注意:你原有逻辑未匹配传入的_ruleName,只要有角色就返回true,实际使用请补充角色名校验 return userRoles.Any(); } }
如果完全不能修改现有构造函数的签名,可以临时用静态服务定位器实现,但这属于DI反模式,仅做兼容用:
// 先定义静态服务定位器 public static class ServiceLocator { public static IServiceProvider RootProvider { get; set; } } // Program.cs中构建完应用后赋值 // var app = builder.Build(); // ServiceLocator.RootProvider = app.Services; // 在IsInRole方法中用作用域解析,避免Scoped服务内存泄漏 // using var scope = ServiceLocator.RootProvider.CreateScope(); // var userRepository = scope.ServiceProvider.GetRequiredService<IFw_UsersRepository>(); // var userRoles = userRepository.GetUserRolls(); // return userRoles.Any();
方案2:方法参数传参(零依赖,测试友好)
如果调用IsInRole方法的位置可以直接拿到IFw_UsersRepository实例,直接把仓储作为方法参数传入即可,不需要在类中持有私有字段,耦合度最低,单元测试时可以直接传入Mock对象:
public bool IsInRole(string _ruleName, IFw_UsersRepository userRepository) { if (userRepository == null) return false; var userRoles = userRepository.GetUserRolls(); return userRoles.Any(); }
方案3:手动实例化依赖(仅临时调试用,不推荐生产)
如果只是临时调试用,可以在方法内部手动构造AppDbContext和对应仓储的实例,但这种方式完全脱离DI容器管理,需要硬编码数据库配置,后续仓储新增依赖时必须同步修改此处代码,维护成本极高:
public bool IsInRole(string _ruleName) { var optionsBuilder = new DbContextOptionsBuilder<AppDbContext>(); // 此处数据库配置必须和启动项中注册的配置完全一致 optionsBuilder.UseSqlServer("你的数据库连接字符串"); using var dbContext = new AppDbContext(optionsBuilder.Options); // Fw_UsersRepository替换为你项目中IFw_UsersRepository的实际实现类名 var userRepository = new Fw_UsersRepository(dbContext); var userRoles = userRepository.GetUserRolls(); return userRoles.Any(); }
内容的提问来源于stack exchange,提问作者javad bayat
相关产品推荐
相关产品推荐

