【问题标题】:Dependency injection in partial class部分类中的依赖注入
【发布时间】:2020-08-25 08:45:50
【问题描述】:

我们正在使用.NET Core 3.1。我们想使用部分类将服务实现拆分为多个文件。代码如下所示:

IAAccountsService.cs

public interface IAccountsService
{
    AppUser Get(string username);
    bool HasRole(string username, int roleId);
    // ...
}

AccountsService.cs

public partial class AccountsService : IAccountsService
{
    private readonly MyDbContext _dbContext;
    
    public AccountsService(MyDbContext dbContext)
    {
        _dbContext = dbContext;
    }
    
    public AppUser Get(string username)
    {
        return _dbContext.AppUser.FirstOrDefault(x => x.Username == username);
    }
}

AccountsService.Roles.cs

public partial class AccountsService : IAccountsService
{
    public bool HasRole(string username, int roleId)
    {
        // _dbContext is null here!
    }
}

AccountsController.cs

private readonly IAccountsService _accountsService;

public AccountsController(IAccountsService accountsService)
{
    _accountsService = accountsService;
}

[HttpGet]
public IActionResult Test1()
{
    // _dbContext is NOT null
    return Ok(_accountsService.Get("admin", 1));
}

[HttpGet]
public IActionResult Test2()
{
    // _dbContext is null
    return Ok(_accountsService.HasRole("admin", 1));
}

我观察到当我调用Test1(调用Get(string username))时,_dbContext 不是null。但是,当我调用Test2(调用HasRole(string username, int roleId))时,_dbContextnull。调用Test2 时,AccountsService.cs 中的构造函数永远不会被命中。

【问题讨论】:

  • 您是否确认将所有代码放在一个文件中可以正常工作? partial 真的不应该对 DI 产生任何影响。
  • AccountsService 中有多个构造函数吗?您还应该像这样添加参数验证:this.dbContext == dbContext ?? throw new ArgumentNullException(nameof(dbContext));.
  • partial 是编译时特性,DI 是运行时特性。不能互相影响。
  • @Dai 是的,AccountsService 中确实有多个构造函数。我删除了它们,现在它可以工作了。
  • "我们希望使用部分类将服务实现拆分为多个文件。"在我看来,您的课程太大了,这会导致可维护性问题。将它们分成部分只会对您有所帮助。您可能在这里违反了单一职责原则。您可能想先解决根本问题。

标签: c# asp.net-core dependency-injection


【解决方案1】:

正如 cmets 中的人所说:“partial 是编译时功能,DI 是运行时。”是编译器将这两个类放在一起,所以如果您在调用HasRole 期间看到_dbContext 为空,这可能意味着一些事情:

  1. AccountsService(MyDbContext dbContext) 构造函数使用null 参数调用。正如你所说的构造函数在Test2 中“从未被命中”,这个选项似乎被证明是错误的。
  2. 调用了不同的构造函数(例如默认 ctor)。如果您有不知道的第三部分类,则可能会出现这种情况。
  3. C# 编译器不会将这两个部分合并为单个 CLR 类型,如果它们都具有不同的命名空间或不同的程序集,则会发生这种情况。在这种情况下,C# 会为“角色”类型生成一个默认构造函数,该构造函数将由 DI 容器调用。

【讨论】:

  • 我有一个不同的构造函数被调用。感谢您指出这一点。
猜你喜欢
  • 1970-01-01
  • 2021-12-26
  • 1970-01-01
  • 2021-09-11
  • 2020-09-19
  • 1970-01-01
  • 2023-04-07
  • 2021-11-23
相关资源
最近更新 更多