#c# #asp.net-core #dependency-injection
#c# #asp.net-core #внедрение зависимости
Вопрос:
Мы используем .NET Core 3.1
. Мы хотим использовать частичные классы для разделения реализации сервиса на несколько файлов. Код выглядит следующим образом:
IAccountsService.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);
}
}
Служба учетных записей.Роли.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)
), _dbContext
является null
. При вызове Test2
конструктор в AccountsService.cs
никогда не попадает.
Комментарии:
1. Вы подтвердили, что все работает нормально, если вместо этого поместить весь код в один файл?
partial
действительно не должно оказывать никакого влияния на DI.2. У вас есть несколько конструкторов в
AccountsService
? Вы также должны добавить проверку аргументов следующим образом:this.dbContext == dbContext ?? throw new ArgumentNullException(nameof(dbContext));
.3.
partial
это функция времени компиляции, DI — среда выполнения. Это не может повлиять друг на друга.4. @Dai Да, действительно, в
AccountsService
было несколько конструкторов. Я удалил их, и теперь это работает.5. «Мы хотим использовать частичные классы для разделения реализации сервиса на несколько файлов». Мне кажется, ваши классы просто слишком большие, что вызывает проблемы с ремонтопригодностью. Разделение их на части поможет вам лишь незначительно. Возможно, здесь вы нарушаете принцип единой ответственности. Возможно, вы захотите сначала устранить основную проблему.
Ответ №1:
Как отметили люди в комментариях: « partial
это функция времени компиляции, DI — это среда выполнения». Это компилятор, объединяющий эти два класса, поэтому, если вы видите, что _dbContext
равно null во время вызова HasRole
, это может означать несколько вещей:
AccountsService(MyDbContext dbContext)
Конструктор вызывается сnull
аргументом. Поскольку вы говорите, что конструктор «никогда не попадает» вTest2
, эти параметры, похоже, оказались ложными.- Вызывается другой конструктор (например, ctor по умолчанию). Это может иметь место, если у вас есть третий частичный класс, о котором вы не знаете.
- Компилятор C # не объединяет две части в один тип CLR, что произойдет, если у них обоих разные пространства имен или разные сборки. В этом случае C # генерирует конструктор по умолчанию для типа «Роли», который будет вызываться контейнером DI.
Комментарии:
1. У меня был другой конструктор, который вызывался. Спасибо, что указали на это.