在ASP.NET Core中为服务和存储库层使用依赖注入的正确方法?

时间:2016-04-29 11:16:31

标签: c# dependency-injection asp.net-core asp.net-core-mvc asp.net-core-1.0

我刚刚在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应该足够了。

2 个答案:

答案 0 :(得分:2)

我的偏好是将其设置如下:

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,就会自动为IUCERRegisterService注入IActiveDirectoryService。 IActiveDirectoryService自动注入WebAppsettings,它可以获取它的配置值。如果所有内容都预先连线,那么您只需要请求将IUserRegisterService实例注入您的控制器。

答案 1 :(得分:2)

  

选项2更可取吗?

没有!我们应该使用选项1的ConfigureServices,但我们会解决您遇到的问题。使用DI,如果您发现自己尝试使用new关键字 - 停止,请深呼吸并重新评估您要实现的目标。

你应该始终使用依赖注入,它是全部或全部。不要让ActiveDirectoryRepository .ctorstring作为参数,而是让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>了吗?这是一件好事,因为这些选项仅用于与此控制器无关的内容。