Запретить ввод IServiceProvider
в компоненты вашего приложения; это приводит к анти-шаблону Service Locator .
Вместо этого вы должны создавать компоненты приложения исключительно с использованием Конструктор Инъекции . Это означает, что ваш AddressService
должен требовать IAddressRepository
в качестве аргумента конструктора, а не IServiceProvider
. Например:
public class AddressService : IAddressService
{
private readonly IAddressRepository repo;
public AddressService(IAddressRepository repo, IUserContext userContext)
{
this.repo = repo;
}
public IReadOnlyList<IState> GetAllStates()
{
// other logic removed
}
}
Также попытайтесь предотвратить внедрение примитивов в ваши конструкторы. Это не плохая практика как таковая, но она усложняет построение графов объектов. Вместо этого либо оберните значение в класс, если оно является значением конфигурации, либо скройте его за абстракцией (как показано выше), если это значение времени выполнения.
Обе практики упрощают как код приложения, так и корень композиции .
Например, это будет результатом предыдущего AddressService
редизайна:
services.AddTransient<IAddressRepository, SqlAddressRepository>();
services.AddTransient<IAddressService, AddressService>();
services.AddScoped<IUserContext, UserContext>();
services.AddHttpContextAccessor();
Здесь UserContext
можно определить следующим образом:
public class UserContext : IUserContext
{
private readonly IHttpContextAccessor accessor;
public UserContext(IHttpContextAccessor accessor) => this.accessor = accessor;
public string UserName => this.accessor.HttpContext.User.Identity.Name;
}