[英]Correct way to use dependency injection in ASP.NET Core for service and repository layers?
I just learned the dependency injection system in ASP.NET Core RC1
. 我刚刚学习了ASP.NET Core RC1
的依赖项注入系统。 I have a controller (code below). 我有一个控制器(下面的代码)。 Option 1 (the line commented out) I've used before. 我以前使用的选项1 (该行已注释掉)。 Option 2 would need to be repeated in each controller and is not preferred. 选项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;
}
}
In the Startup.cs\\Configure\\ConfigureServices
we have the following. 在Startup.cs\\Configure\\ConfigureServices
我们具有以下内容。
Option 1: 选项1:
services.AddTransient<Admin.Interfaces.IActiveDirectoryRepository,
Admin.Repositories.ActiveDirectoryRepository>();
services.AddTransient<Admin.Interfaces.IUserRegisterService,
Admin.Services.UserRegisterService>();
Option 2: 选项2:
services.AddTransient<Admin.Interfaces.IActiveDirectoryRepository,
Admin.Repositories.ActiveDirectoryRepository>();
services.AddTransient<Admin.Interfaces.IUserRegisterService,
Admin.Services.UserRegisterService>(provider =>
new UserRegisterService(
new ActiveDirectoryRepository(
Configuration["ContainerDomain"])));
Is option 2 the preferred implementation? 选项2是首选实现吗? I want to avoid using a third-party library for dependency injection. 我想避免使用第三方库进行依赖项注入。 I think for my needs the standard means ASP.NET Core DI
should be sufficient. 我认为对于我的需求,标准意味着ASP.NET Core DI
应该足够。
My preference would be to set it up as follows: 我希望将其设置如下:
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>();
}
this way you have your IUserRegisterService get automatically injected with the IActiveDirectoryService anytime you resolve the IUserRegisterService. 这样,您在解决IUserRegisterService时就可以将IUserRegisterService自动注入IActiveDirectoryService。 The IActiveDirectoryService automatically gets injected with your WebAppsettings, where it can get it's config value. IActiveDirectoryService会自动与您的WebAppsettings一起注入,在那里可以获取它的配置值。 If everything is pre-wired like this then you only need to request that an instance of IUserRegisterService be injected into your controller. 如果一切都是这样预接线的,那么您只需要请求将IUserRegisterService实例注入您的控制器即可。
Is option 2 more preferable? 选项2更可取吗?
No! 没有! We should use the ConfigureServices
of option 1, but we will fix the issue you're having. 我们应该使用选项1的ConfigureServices
,但是我们将解决您遇到的问题。 With DI, if you find yourself attempting to use the new
keyword -- stop, take a deep breath and reevaluate what you're trying to achieve. 使用DI,如果您发现自己尝试使用new
关键字-停止,请深呼吸,然后重新评估要实现的目标。
You should use dependency injection throughout, it's all or nothing. 您应该始终使用依赖项注入,这是全部或全部。 Instead of having the ActiveDirectoryRepository .ctor
take a string
as a parameter, have it take on the IOptions<WebAppSettings>
instead. 与其让ActiveDirectoryRepository .ctor
接受一个string
作为参数,不如让它接受IOptions<WebAppSettings>
。 This is part of the standard ASP.NET Core
dependency injection and is preferred. 这是标准ASP.NET Core
依赖项注入的一部分,因此是首选。
First, the ActiveDirectoryRepository
as I described above. 首先,如上所述的ActiveDirectoryRepository
。 The _container
variable is set from the settings as desired. _container
变量是根据需要从设置中设置的。
internal class UserRegisterService : IUserRegisterService
{
private readonly IActiveDirectoryRepository _repoAd;
internal UserRegisterService(IActiveDirectoryRepository repoAd)
{
_repoAd = repoAd;
}
}
Next, the UserRegisterService
implementation can stay exactly as you have it now. 接下来, UserRegisterService
实现可以完全保持现在的状态。
public class UserRegisterController : Controller
{
private readonly IUserRegisterService _userRegisterService;
private readonly UserManager<ApplicationUser> _userManager;
public UserRegisterController(
UserManager<ApplicationUser> userManager,
IUserRegisterService userRegisterService)
{
_userManager = userManager;
_userRegisterService = userRegisterService;
}
}
Finally, your UserRegisterController
is simplified as follows: 最后,将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; } }
Notice, we no longer need the IOptions<WebAppSettings>
here? 注意,我们在这里不再需要IOptions<WebAppSettings>
了吗? This is a good thing as the options were only being used for something unrelated to this controller specifically. 这是一件好事,因为这些选项仅用于与该控制器无关的内容。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.