Single Responsibility提供了更多的依赖关系,如何解决此问题

本文关键字:何解决 解决 问题 关系 Responsibility 依赖 Single | 更新日期: 2023-09-27 17:59:15

我有一个MVC控制器,它包含几个抽象(组件)。我想把params的数量减少到最多4个params。

要做到这一点,我有几个策略不能满足:

  • 将一组params绑定到一个新的类中,其中params将是属性:这只是掩盖了复杂性
  • 解决依赖关系不是通过构造函数注入,而是通过使用工厂:这也掩盖了复杂性

有更好的替代方法吗?

这是控制器的代码:

public abstract class BaseVerificatieController : ExtendedController
    {
        private readonly IReferentieTabellenSysteemSettings referentieTabellenSysteemSettings;
        private readonly IProcessManager processManager;
        private readonly INavigationManager navigationManager;
        private readonly ITransactionFacade transactionFacade;
        private readonly IUISupportFacade uiSupportFacade;
        private readonly ProcessIndex process;
        protected BaseVerificatieController(
            IBackHandler backHandler,
            IReferentieTabellenSysteemSettings referentieTabellenSysteemSettings,
            IProcessManager processManager,
            INavigationManager navigationManager,
            ITransactionFacade transactionFacade,
            IUISupportFacade uiSupportFacade,
            ProcessIndex process)
            : base(backHandler)
        {
            this.referentieTabellenSysteemSettings = referentieTabellenSysteemSettings;
            this.processManager = processManager;
            this.navigationManager = navigationManager;
            this.transactionFacade = transactionFacade;
            this.uiSupportFacade = uiSupportFacade;
            this.process = process;
        }
        [HttpGet]
        public ActionResult Index()
        {
            var processStep = processManager.StartProcess(process);
            return navigationManager.RedirectFromProcessStep(process, processStep);
        }
        [HttpGet]
        public ActionResult Oe()
        {
            var model = new OeViewModel();
            var transactionResult = transactionFacade.VerifyIdentityStart();
            model.SetTransactionResult(transactionResult);
            return View(model);
        }
        [HttpPost]
        public ActionResult Oe(OeViewModel viewModel)
        {
            if (viewModel == null)
            {
                throw new ArgumentNullException("viewModel");
            }
            var transactionResult = transactionFacade.VerifyIdentityCheckRegisters(viewModel.SKN, null);
            if (transactionResult.MoveToStep != Business.Models.ProcessStepIndex.NoStep)
            {
                return navigationManager.RedirectFromTransactionResult(process, transactionResult);
            }
            var model = new OeViewModel();
            model.SetTransactionResult(transactionResult);
            return View(model);
        }
        [HttpGet]
        public ActionResult Oz()
        {
            var model = new OzViewModel(uiSupportFacade, referentieTabellenSysteemSettings);
            var idStaatResult = transactionFacade.IdStaatStart();
            model.SetIdStaatResult(idStaatResult);
            return View("Oz_SKDB", model);
        }
        [HttpPost]
        public ActionResult Oz(OzViewModel viewModel)
        {
            return RedirectToAction("Index", "Home");
        }

Single Responsibility提供了更多的依赖关系,如何解决此问题

正如@Maarten在评论中所说,我会取消process的注入,并将其注入到需要的地方(而不是四处传递)。

我将进一步将所有视图模型逻辑移动到"视图模型处理程序"中,并使用中介来执行视图模型处理。

然后,诸如transactionFacadeuiSupportFacade之类的依赖关系将被注入视图模型处理程序中。这可以通过以下方式实现:

 /// <summary>
/// Specifices that the target class is a view model. This is a marker interface and has no methods.
/// </summary>
public interface IViewModel
{
    // Marker interface
}
/// <summary>
/// Handles the <typeparamref name="TViewModel"/>.
/// </summary>
/// <typeparam name="TViewModel">The view model which should be handled.</typeparam>
public interface IHandleViewModel<out TViewModel> where TViewModel : IViewModel
{
    /// <summary>
    /// Creates a <typeparamref name="TViewModel"/>.
    /// </summary>
    /// <returns>An instance of the <typeparamref name="TViewModel"/>.</returns>
    TViewModel Handle();
}
/// <summary>
/// Handles the <typeparamref name="TViewModel"/> with the argument of <typeparamref name="TInput"/>
/// </summary>
/// <typeparam name="TInput">The argument for the view model</typeparam>
/// <typeparam name="TViewModel">The view model which should be handled.</typeparam>
public interface IHandleViewModel<out TViewModel, in TInput> where TViewModel : IViewModel
{
    /// <summary>
    /// Creates a <typeparamref name="TViewModel"/>.
    /// </summary>
    /// <returns>An instance of the <typeparamref name="TViewModel"/>.</returns>
    TViewModel Handle(TInput input);
}
/// <summary>
/// Processes and creates view models.
/// </summary>
public interface IProcessViewModels
{
    /// <summary>
    /// Creates the <typeparamref name="TViewModel"/>.
    /// </summary>
    /// <returns>The view model</returns>
    TViewModel Create<TViewModel>() where TViewModel : IViewModel;
    /// <summary>
    /// Create the <typeparamref name="TViewModel"/> with an argument of type <typeparamref name="TInput"/> 
    /// </summary>
    /// <typeparam name="TViewModel">The view model which should be constructed</typeparam>
    /// <typeparam name="TInput">The type of argument for the view model</typeparam>
    /// <param name="input">The argument for the view model</param>
    /// <returns>The view model</returns>
    TViewModel Create<TViewModel, TInput>(TInput input) where TViewModel : IViewModel;
}

这意味着您可以将单个IProcessViewModels注入控制器并执行处理程序。例如,通过填充依赖容器(此处为Simple Injector):

/// <summary>
/// Registers the view models in the Simple Injector container
/// </summary>
/// <param name="container">The Simple Injector container</param>
/// <param name="viewModelAssemblies">The assembly location of the view models</param>
public static void RegisterViewModels(this Container container, Assembly[] viewModelAssemblies)
{
    if (container == null)
        throw new ArgumentNullException("container");
    if (viewModelAssemblies == null) 
        throw new ArgumentNullException("viewModelAssemblies");
    container.RegisterSingle<IProcessViewModels, ViewModelProcessor>();
    container.RegisterManyForOpenGeneric(typeof(IHandleViewModel<>), viewModelAssemblies);
    container.RegisterManyForOpenGeneric(typeof(IHandleViewModel<,>), viewModelAssemblies);
}

以上代码来自我的"神经框架":https://github.com/janhartmann/nerve-framework/tree/master/NerveFramework.Web.Mvc