Jos*_*osh 1 c# dependency-injection .net-core asp.net-core
我有一个包含以下项目的解决方案
过去,我在完整框架项目中使用Unity for DI。我能够将具体对象注册到可执行项目(Web应用程序,控制台应用程序,测试应用程序)中的接口映射。
我正在尝试使用.NET Core实现相同的方法。我想首先尝试使用Microsoft.Extensions.DependencyInjection库。在ASP.NET Core应用程序中,它运行良好。不幸的是,当我尝试与注册共享/引用该实例到其他项目(例如.NET Standard库)时,遇到了一个问题。
我的想法是将ServiceProvider注入服务的构造函数中:
public class AddressService : BaseService, IAddressService
{
private readonly IServiceProvider _serviceProvider;
public AddressService(IServiceProvider serviceProvider, string userOrProcessName)
{
_serviceProvider = serviceProvider;
}
public IReadOnlyList<IState> GetAllStates()
{
_serviceProvider.GetService<IAddressRepository>();
// other logic removed
}
}
Run Code Online (Sandbox Code Playgroud)
我在Startup.ConfigureServices()中尝试了以下方法:
services.AddTransient<IAddressService>(s => new AddressService(HttpContext.RequestServices, Environment.UserName));
Run Code Online (Sandbox Code Playgroud)
我遇到的问题是我无法在Controller外部引用HttpContext.RequestServices。我还没有找到传递ServiceProvider实例的另一种方法。
我的问题:
防止注入IServiceProvider您的应用程序组件;导致服务定位器反模式。
相反,您应该仅使用Constructor Injection构建应用程序组件。这意味着您AddressService应该要求IAddressRepositoryas作为构造函数参数,而不是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
}
}
Run Code Online (Sandbox Code Playgroud)
还要尝试防止将素数注入构造函数中。这本身并不是一个坏习惯,但是它确实使对象图的构造变得复杂。相反,可以将值包装到一个类中(以防它是配置值),或者将其隐藏在一个抽象后面(如上所示),以防它是运行时值。
两种做法都简化了应用程序代码和“ 合成根”。
例如,这将是先前AddressService重新设计的结果:
services.AddTransient<IAddressRepository, SqlAddressRepository>();
services.AddTransient<IAddressService, AddressService>();
services.AddScoped<IUserContext, UserContext>();
services.AddHttpContextAccessor();
Run Code Online (Sandbox Code Playgroud)
在这里,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;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
454 次 |
| 最近记录: |