在 ASP.NET 核心中为服务和存储库层使用依赖注入的正确方法?
Correct way to use dependency injection in ASP.NET Core for service and repository layers?
刚刚在ASP.NET Core RC1
学习了依赖注入系统。我有一个控制器(下面的代码)。 选项1(注释掉的那一行)我以前用过。 选项 2 需要在每个控制器中重复并且不是首选。
public class UserRegisterController : Controller
{
private readonly IUserRegisterService _userRegisterService;
private readonly UserManager<ApplicationUser> _userManager;
public UserRegisterController(
UserManager<ApplicationUser> userManager,
IOptions<WebAppSettings> settings,
IUserRegisterService userRegisterService)
{
_userManager = userManager;
// Option 2
_userRegisterService = userRegisterService;
// Option 1
//_userRegisterService =
// new UserRegisterService(
// new ActiveDirectoryRepository(settings.Value.ContainerDomain));
}
}
internal class UserRegisterService : IUserRegisterService
{
private readonly IActiveDirectoryRepository _repoAd;
internal UserRegisterService(IActiveDirectoryRepository repoAd)
{
_repoAd = repoAd;
}
}
internal class ActiveDirectoryRepository : IActiveDirectoryRepository
{
private readonly string _container;
public ActiveDirectoryRepository(string container)
{
_container = container;
}
}
在 Startup.cs\Configure\ConfigureServices
中我们有以下内容。
选项 1:
services.AddTransient<Admin.Interfaces.IActiveDirectoryRepository,
Admin.Repositories.ActiveDirectoryRepository>();
services.AddTransient<Admin.Interfaces.IUserRegisterService,
Admin.Services.UserRegisterService>();
选项 2:
services.AddTransient<Admin.Interfaces.IActiveDirectoryRepository,
Admin.Repositories.ActiveDirectoryRepository>();
services.AddTransient<Admin.Interfaces.IUserRegisterService,
Admin.Services.UserRegisterService>(provider =>
new UserRegisterService(
new ActiveDirectoryRepository(
Configuration["ContainerDomain"])));
选项 2 是首选实施方式吗?我想避免使用第三方库进行依赖注入。我认为对于我的需要,标准方法 ASP.NET Core DI
应该足够了。
我的偏好是设置如下:
public class UserRegisterController : Controller
{
private readonly UserManager<ApplicationUser> _userManager;
private IUserRegisterService _userRegisterService;
public UserRegisterController(
UserManager<ApplicationUser> userManager,
IOptions<WebAppSettings> settings,
IUserRegisterService userRegisterService)
{
_userManager = userManager;
_userRegisterService = userRegisterService;
}
//...
}
internal class UserRegisterService : IUserRegisterService
{
private readonly IActiveDirectoryRepository _repoAd;
public UserRegisterService(IActiveDirectoryRepository repoAd)
{
_repoAd = repoAd;
}
}
internal class ActiveDirectoryRepository : IActiveDirectoryRepository
{
private readonly string _container;
public ActiveDirectoryRepository(IOptions<WebAppSettings> settings)
{
_container = settings.Value.ContainerDomain;
}
}
public class WebAppSettings
{
public string ContainerDomain { get; set; }
}
public void ConfigureServices(IServiceCollection services)
{
services.AddOptions();
services.Configure<WebAppSettings>(Configuration);
// Add framework services.
services.AddMvc();
services.AddTransient<IActiveDirectoryRepository, ActiveDirectoryRepository>();
services.AddTransient<IUserRegisterService, UserRegisterService>();
}
这样,只要您解析 IUserRegisterService,您的 IUserRegisterService 就会自动注入 IActiveDirectoryService。 IActiveDirectoryService 会自动注入您的 WebAppsettings,它可以在其中获取其配置值。如果一切都像这样预先连接,那么您只需要请求将 IUserRegisterService 的实例注入到您的控制器中。
Is option 2 more preferable?
没有!我们应该使用选项 1 的 ConfigureServices
,但我们会解决您遇到的问题。对于 DI,如果您发现自己试图使用 new
关键字——停下来,深呼吸并重新评估您要达到的目标。
你应该自始至终使用依赖注入,要么全有要么全无。与其让 ActiveDirectoryRepository .ctor
接受 string
作为参数,不如让它接受 IOptions<WebAppSettings>
作为参数。这是标准 ASP.NET Core
依赖注入的一部分,是首选。
让我们回顾一下您最终会得到什么...
首先,ActiveDirectoryRepository
如上所述。 _container
变量根据需要从设置中设置。
internal class ActiveDirectoryRepository : IActiveDirectoryRepository
{
private readonly string _container;
public ActiveDirectoryRepository(IOptions<WebAppSettings> settings)
{
_container = settings.Value.ContainerDomain;
}
}
接下来,UserRegisterService
实现可以与您现在拥有的完全一样。
internal class UserRegisterService : IUserRegisterService
{
private readonly IActiveDirectoryRepository _repoAd;
internal UserRegisterService(IActiveDirectoryRepository repoAd)
{
_repoAd = repoAd;
}
}
最后,你的UserRegisterController
简化如下:
public class UserRegisterController : Controller
{
private readonly IUserRegisterService _userRegisterService;
private readonly UserManager<ApplicationUser> _userManager;
public UserRegisterController(
UserManager<ApplicationUser> userManager,
IUserRegisterService userRegisterService)
{
_userManager = userManager;
_userRegisterService = userRegisterService;
}
}
注意,我们不再需要这里的 IOptions<WebAppSettings>
了吗?这是一件好事,因为这些选项仅用于与此控制器无关的特定内容。
刚刚在ASP.NET Core RC1
学习了依赖注入系统。我有一个控制器(下面的代码)。 选项1(注释掉的那一行)我以前用过。 选项 2 需要在每个控制器中重复并且不是首选。
public class UserRegisterController : Controller
{
private readonly IUserRegisterService _userRegisterService;
private readonly UserManager<ApplicationUser> _userManager;
public UserRegisterController(
UserManager<ApplicationUser> userManager,
IOptions<WebAppSettings> settings,
IUserRegisterService userRegisterService)
{
_userManager = userManager;
// Option 2
_userRegisterService = userRegisterService;
// Option 1
//_userRegisterService =
// new UserRegisterService(
// new ActiveDirectoryRepository(settings.Value.ContainerDomain));
}
}
internal class UserRegisterService : IUserRegisterService
{
private readonly IActiveDirectoryRepository _repoAd;
internal UserRegisterService(IActiveDirectoryRepository repoAd)
{
_repoAd = repoAd;
}
}
internal class ActiveDirectoryRepository : IActiveDirectoryRepository
{
private readonly string _container;
public ActiveDirectoryRepository(string container)
{
_container = container;
}
}
在 Startup.cs\Configure\ConfigureServices
中我们有以下内容。
选项 1:
services.AddTransient<Admin.Interfaces.IActiveDirectoryRepository,
Admin.Repositories.ActiveDirectoryRepository>();
services.AddTransient<Admin.Interfaces.IUserRegisterService,
Admin.Services.UserRegisterService>();
选项 2:
services.AddTransient<Admin.Interfaces.IActiveDirectoryRepository,
Admin.Repositories.ActiveDirectoryRepository>();
services.AddTransient<Admin.Interfaces.IUserRegisterService,
Admin.Services.UserRegisterService>(provider =>
new UserRegisterService(
new ActiveDirectoryRepository(
Configuration["ContainerDomain"])));
选项 2 是首选实施方式吗?我想避免使用第三方库进行依赖注入。我认为对于我的需要,标准方法 ASP.NET Core DI
应该足够了。
我的偏好是设置如下:
public class UserRegisterController : Controller
{
private readonly UserManager<ApplicationUser> _userManager;
private IUserRegisterService _userRegisterService;
public UserRegisterController(
UserManager<ApplicationUser> userManager,
IOptions<WebAppSettings> settings,
IUserRegisterService userRegisterService)
{
_userManager = userManager;
_userRegisterService = userRegisterService;
}
//...
}
internal class UserRegisterService : IUserRegisterService
{
private readonly IActiveDirectoryRepository _repoAd;
public UserRegisterService(IActiveDirectoryRepository repoAd)
{
_repoAd = repoAd;
}
}
internal class ActiveDirectoryRepository : IActiveDirectoryRepository
{
private readonly string _container;
public ActiveDirectoryRepository(IOptions<WebAppSettings> settings)
{
_container = settings.Value.ContainerDomain;
}
}
public class WebAppSettings
{
public string ContainerDomain { get; set; }
}
public void ConfigureServices(IServiceCollection services)
{
services.AddOptions();
services.Configure<WebAppSettings>(Configuration);
// Add framework services.
services.AddMvc();
services.AddTransient<IActiveDirectoryRepository, ActiveDirectoryRepository>();
services.AddTransient<IUserRegisterService, UserRegisterService>();
}
这样,只要您解析 IUserRegisterService,您的 IUserRegisterService 就会自动注入 IActiveDirectoryService。 IActiveDirectoryService 会自动注入您的 WebAppsettings,它可以在其中获取其配置值。如果一切都像这样预先连接,那么您只需要请求将 IUserRegisterService 的实例注入到您的控制器中。
Is option 2 more preferable?
没有!我们应该使用选项 1 的 ConfigureServices
,但我们会解决您遇到的问题。对于 DI,如果您发现自己试图使用 new
关键字——停下来,深呼吸并重新评估您要达到的目标。
你应该自始至终使用依赖注入,要么全有要么全无。与其让 ActiveDirectoryRepository .ctor
接受 string
作为参数,不如让它接受 IOptions<WebAppSettings>
作为参数。这是标准 ASP.NET Core
依赖注入的一部分,是首选。
让我们回顾一下您最终会得到什么...
首先,ActiveDirectoryRepository
如上所述。 _container
变量根据需要从设置中设置。
internal class ActiveDirectoryRepository : IActiveDirectoryRepository
{
private readonly string _container;
public ActiveDirectoryRepository(IOptions<WebAppSettings> settings)
{
_container = settings.Value.ContainerDomain;
}
}
接下来,UserRegisterService
实现可以与您现在拥有的完全一样。
internal class UserRegisterService : IUserRegisterService
{
private readonly IActiveDirectoryRepository _repoAd;
internal UserRegisterService(IActiveDirectoryRepository repoAd)
{
_repoAd = repoAd;
}
}
最后,你的UserRegisterController
简化如下:
public class UserRegisterController : Controller
{
private readonly IUserRegisterService _userRegisterService;
private readonly UserManager<ApplicationUser> _userManager;
public UserRegisterController(
UserManager<ApplicationUser> userManager,
IUserRegisterService userRegisterService)
{
_userManager = userManager;
_userRegisterService = userRegisterService;
}
}
注意,我们不再需要这里的 IOptions<WebAppSettings>
了吗?这是一件好事,因为这些选项仅用于与此控制器无关的特定内容。