单一责任提供了更多的依赖关系,如何解决此问题

时间:2015-06-24 08:18:45

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

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

为此,我有几个不满足的策略:

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

有更好的替代方法吗?

这是控制器的代码:

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");
        }

1 个答案:

答案 0 :(得分:1)

正如@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);
}

以上代码来自我的&#34; Nerve Framework&#34;在这里:https://github.com/janhartmann/nerve-framework/tree/master/NerveFramework.Web.Mvc