.Net Core 2.0中Controller和BaseController中的依赖项注入重复 [英] Dependency injection duplication in Controller and BaseController in .Net Core 2.0

查看:359
本文介绍了.Net Core 2.0中Controller和BaseController中的依赖项注入重复的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我在Asp.Net Core 2.0 Web应用程序中创建了一个BaseController,它封装了一些常见的依赖关系,那么在实际的控制器中它们仍然是必需的.

If I create a BaseController in my Asp.Net Core 2.0 web application that capsulizes some of the common dependencies are they still necessary in the actual controllers.

例如,默认MVC 6 Web应用程序中的标准帐户"和管理"控制器.

For Example, the standard Account and Manage controllers in a default MVC 6 web application.

public class AccountController : Controller
{
    private readonly UserManager<ApplicationUser> _userManager;
    private readonly SignInManager<ApplicationUser> _signInManager;
    private readonly IEmailSender _emailSender;
    private readonly ILogger _logger;

    public AccountController(
        UserManager<ApplicationUser> userManager,
        SignInManager<ApplicationUser> signInManager,
        IEmailSender emailSender,
        ILogger<AccountController> logger)
    {
        _userManager = userManager;
        _signInManager = signInManager;
        _emailSender = emailSender;
        _logger = logger;
    }
   //rest of code removed
}

public class ManageController : Controller
{
    private readonly UserManager<ApplicationUser> _userManager;
    private readonly SignInManager<ApplicationUser> _signInManager;
    private readonly IEmailSender _emailSender;
    private readonly ILogger _logger;
    private readonly UrlEncoder _urlEncoder;

    private const string AuthenicatorUriFormat = "otpauth://totp/{0}:{1}?secret={2}&issuer={0}&digits=6";

    public ManageController(
      UserManager<ApplicationUser> userManager,
      SignInManager<ApplicationUser> signInManager,
      IEmailSender emailSender,
      ILogger<ManageController> logger,
      UrlEncoder urlEncoder)
    {
        _userManager = userManager;
        _signInManager = signInManager;
        _emailSender = emailSender;
        _logger = logger;
        _urlEncoder = urlEncoder;
    }
    // rest of code removed
}

在我正在构建的定制Web应用程序模板中,我将帐户控制器重构为三个不同的控制器,RegisterController(负责处理与用户注册有关的所有内容),LoginController(处理登录和注销),以及余额中的三分之一.我将Manage Controller一分为二,一个ManagePasswordController(与密码有关的所有内容)和一个UserManageController(与密码有关的其他所有内容).

In the custom web application template I am building I refactor the Account Controller to three different Controllers, RegisterController(Which handles everything regarding a user registration), LoginController(which handles login and logout), and the balance into a third. I split the Manage Controller in two, a ManagePasswordController(everything related to passwords) and a UserManageController(everything else).

每个DI的要求都有很多共同点,我想将它们放在BaseController中.要看起来像这样吗?

There is a lot of commonality in the DI requirements for each and I want to put them in a BaseController. To look something like this?

public abstract class BaseController : Controller
{
    private readonly IConfiguration _config;
    private readonly IEmailSender _emailSender;
    private readonly ILogger _logger;
    private readonly SignInManager<ApplicationUser> _signInManager;
    private readonly UserManager<ApplicationUser> _userManager;

     protected BaseController(IConfiguration iconfiguration,
        UserManager<ApplicationUser> userManager,
        SignInManager<ApplicationUser> signInManager,
        IEmailSender emailSender,
        ILogger<ManageController> logger)
    {
        _config = iconfiguration;
        _userManager = userManager;
        _signInManager = signInManager;
        _emailSender = emailSender;
        _logger = logger;
    }
    //rest of code removed
}

但是似乎什么也做不了?因为在我看来,我仍然必须注入所有东西.我不能说对(我是DI的新手,所以显然没有任何线索),但是BaseController应该允许我做BaseController和RegisterController之间不常见的DI.我错了吗?我该如何完成我想做的事情?

But it seems like that accomplishes nothing? because it seems to me I still have to inject everything. I can't be right (I'm new to DI so clearly have no clue) but the BaseController should allow me to do NO DI that's common between BaseController and RegisterController. Am I wrong? How do I accomplish what I am trying to do?

public class RegisterController : BaseController
{
    private const string ConfirmedRegistration = "User created a new account with password.";

    private readonly UserManager<ApplicationUser> _userManager;
    private readonly SignInManager<ApplicationUser> _signInManager;
    private readonly IEmailSender _emailSender;
    private readonly ILogger _logger;
    private readonly IConfiguration _config;

     public RegisterController(
        IConfiguration config,
        UserManager<ApplicationUser> userManager,
        SignInManager<ApplicationUser> signInManager,
        IEmailSender emailSender,
        ILogger<AccountController> logger) : base(config, userManager, signInManager, emailSender, logger)

    {
        _userManager = userManager;
        _signInManager = signInManager;
        _emailSender = emailSender;
        _logger = logger;
        _config = config;
    }
    //rest of code removed
}

更新

根据鲁弗爵士的建议

public abstract class BaseController : Controller
{
    protected UserManager<ApplicationUser> UserManager { get; }
    protected SignInManager<ApplicationUser> SignInManager { get; }
    protected IConfiguration Config { get; }
    protected IEmailSender EmailSender { get; }
    protected ILogger AppLogger { get; }

    protected BaseController(IConfiguration iconfiguration,
        UserManager<ApplicationUser> userManager,
        SignInManager<ApplicationUser> signInManager,
        IEmailSender emailSender,
        ILogger<ManageController> logger)
    {
        AppLogger = logger;
        EmailSender = emailSender;
        Config = iconfiguration;
        SignInManager = signInManager;
        UserManager = userManager; 
    }
}

和继承控制器

public class TestBaseController : BaseController
{

    public TestBaseController() : base()
    {

    }
}

这不起作用. Resharper告诉我,我必须将参数添加到TestBaseController构造函数中的基本构造函数调用中.

This doesn't work. Resharper is telling me I have to add the parameters to the base constructor call in the TestBaseController constructor.

BaseController还应该从.Net Core 2.0中的Controller或ControllerBase继承吗?

Also should BaseController be inheriting from Controller or ControllerBase in .Net Core 2.0?

推荐答案

有很多在MVC中使用BaseController的理由很少.在这种情况下,基本控制器只会添加更多要维护的代码,而没有真正的好处.

There are very few good reasons to use a BaseController in MVC. A base controller in this scenario only adds more code to maintain, with no real benefit.

对于真正的跨领域关注点,这是最常见的解决方法在MVC中处理它们是使用全局过滤器, MVC内核中有一些值得考虑的新选项.

For true cross-cutting concerns, the most common way to handle them in MVC is to use global filters, although there are a few new options worth considering in MVC core.

但是,您的问题看起来并不像是一个跨领域的关注,而是违反了单个责任原则.也就是说,具有3个以上的注入依赖项是一种代码异味,说明您的控制器执行了太多操作.最实用的解决方案是重构为聚合服务.

However, your problem doesn't look like a cross-cutting concern so much as a violation of the Single Responsibility Principle. That is, having more than 3 injected dependencies is a code smell that your controller is doing too much. The most practical solution would be to Refactor to Aggregate Services.

在这种情况下,我认为您有至少1个需要显式的隐式服务-即UserManagerSignInManager应该包装成自己的服务.从那里,您可能会将其他3个依赖项注入到该服务中(当然,取决于它们的使用方式).因此,对于AccountControllerManageController,您可能会将其缩减为单个依赖项.

In this case, I would argue that you have at least 1 implicit service that you need to make explicit - namely, UserManager and SignInManager should be wrapped into a service of its own. From there, you could potentially inject your other 3 dependencies into that service (depending on how they are used, of course). So, you could potentially whittle this down to a single dependency for both the AccountController and ManageController.

一些迹象表明控制器做得太多:

Some signs that a controller is doing too much:

  1. 有很多辅助"方法,其中包含在操作之间共享的业务逻辑.
  2. 动作方法的作用不只是简单的HTTP请求/响应.动作方法通常不应执行任何操作,而应调用处理输入和/或产生输出并返回视图和响应代码的服务.

在这种情况下,值得一看的是,您是否可以将该逻辑移到它们自己的服务中,以及是否将任何共享逻辑移到该服务的依赖项中,等等.

In cases such as these, it is worth a look to see if you can move that logic into a service of their own and any shared logic into dependencies of that service, etc.

这篇关于.Net Core 2.0中Controller和BaseController中的依赖项注入重复的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆