注入了asp.net mvc控制器构造函数中的多个依赖项

时间:2012-08-04 19:30:30

标签: asp.net-mvc model-view-controller dependency-injection controller

在我的asp.net mvc controller的构造函数中,我有多个(5)接口以这种方式与我的数据库通信:

[HttpGet]
public ActionResult Create()
{          
 var releases = _releaseDataProvider.GetReleases();
 var templates = _templateDataProvider.GetTemplates();
 var createTestplanViewModel = new CreateTestplanViewModel(templates, releases);
 return PartialView(createTestplanViewModel);
}

上面我使用2个不同的接口从数据库中获取数据。

业务案例:要创建测试计划,我需要向用户显示他可以选择的可用版本+模板。

如何减少这两个接口的依赖性/过度注入

3 个答案:

答案 0 :(得分:1)

在MVC项目中:

public class MyController : Controller
{
    private readonly IQueryProcessor _queryProcessor;

    public MyController(IQueryProcessor queryProcessor)
    {
        _queryProcessor = queryProcessor;
    }

    [HttpGet]
    public ActionResult Create()
    {
        var releases = _queryProcessor.Execute(new ProvideReleaseData());
        var templates = _queryProcessor.Execute(new ProvideTemplateData());
        var createTestplanViewModel = AutoMapper.Mapper
            .Map<CreateTestplanViewModel>(releases);
        AutoMapper.Mapper.Map(templates, createTestplanViewModel);
        return PartialView(createTestplanViewModel);
    }
}

然后,构造函数可以将当前的提供程序实现注入IQueryHandler实现。 IQueryProcessor只是基础设施。有关详情,请参阅此处:https://cuttingedge.it/blogs/steven/pivot/entry.php?id=92

回复评论:

它位于我链接的网站上。这是我的:

using System.Diagnostics;
using SimpleInjector;

namespace MyApp.Infrastructure
{
    sealed class SimpleQueryProcessor : IQueryProcessor
    {
        private readonly Container _container;

        public SimpleQueryProcessor(Container container)
        {
            _container = container;
        }

        [DebuggerStepThrough]
        public TResult Execute<TResult>(IDefineQuery<TResult> query)
        {
            var handlerType = typeof(IHandleQueries<,>)
                .MakeGenericType(query.GetType(), typeof(TResult));

            dynamic handler = _container.GetInstance(handlerType);

            return handler.Handle((dynamic)query);
        }
    }
}

答案 1 :(得分:0)

修改

在我看来,你基本上有这些选项来减少构造函数依赖计数:

  1. 拆分控制器
  2. 在两个界面前添加图层
  3. 切换到属性注入
  4. 服务定位器
  5. 包含#3和#4是为了衡量,但它们实际上并没有减少依赖计数,它们只是将它们隐藏在构造函数中。它们也有一些缺点,我认为服务定位器在大多数时候都是特别邪恶的。

    对于#1,如果您觉得您的构造函数实际上正在执行两个+作业,并且存在可以拆分的干净分离,我会这样做。我从你的回答中假设你已经考虑过这个,但是不想这样做。

    留下#2 - 添加另一层。在这种情况下,将为该特定视图模型引入工厂接口。天真地,我将这个ICreateTestplanViewModelFactory命名为,但如果你愿意的话,你可以为它的应用命名。它上面的一个方法将构造一个CreateTestplanViewModel。

    这使得该视图的数据来自2个源仅仅是实现细节。您将连接一个实现,该实现将IReleaseDataProvider和ITemplateDataProvider作为构造函数依赖项。


    这与我的建议一致:

    public interface IProvideTestPlanSetupModel
    {
        CreateTestplanViewModel GetModel();
    }
    
    public class TestPlanSetupProvider : IProvideTestPlanSetupModel
    {
        private readonly IReleaseDataProvider _releaseDataProvider;
        private readonly ITemplateDataProvider _templateDataProvider;
    
        public TestPlanSetupProvider(IReleaseDataProvider releaseDataProvider, ITemplateDataProvider templateDataProvider)
        {
            _releaseDataProvider = releaseDataProvider;
            _templateDataProvider = templateDataProvider;
        }
    
        public CreateTestplanViewModel GetModel()
        {
            var releases = _releaseDataProvider.GetReleases();
            var templates = _templateDataProvider.GetTemplates();
    
            return new CreateTestplanViewModel(releases, templates);
        }
    }
    
    public class TestPlanController : Controller
    {
        private readonly IProvideTestPlanSetupModel _testPlanSetupProvider;
    
        public TestPlanController(IProvideTestPlanSetupModel testPlanSetupProvider)
        {
            _testPlanSetupProvider = testPlanSetupProvider;
        }
    
        [HttpGet]
        public ActionResult Create()
        {
            var createTestplanViewModel = _testPlanSetupProvider.GetModel();
            return PartialView(createTestplanViewModel);
        }
    }
    

    如果您不喜欢在控制器外部的任何位置构建视图模型,则该接口可以提供具有您要复制到视图模型的相同属性的中间对象。但这很愚蠢,因为这种数据组合仅与特定视图相关,这正是视图模型应该代表的。

    另一方面,您似乎遇到了通过相同模型进行读/写操作的相当常见的烦恼。由于这些问题让您感到困扰,您可能会调查CQRS,这可能会让您感觉不那么直接与数据库进行这些类型的查询交流,并且可以帮助您绕过我们都非常喜欢的分层迷宫。虽然我还没有在测试中将其驱动到生产应用程序中,但它似乎很有希望。

答案 2 :(得分:0)

解耦数据库的一般方法是使用一个工作单元。以下是来自asp.net的精彩文章,以及MSDN上的另一篇文章。

总之,您创建一个单元,其中包含所有数据库/服务调用,并且它可以处理数据库逻辑。这会将多个接口的依赖性降低到一个点,因此您只需要将1个类注入控制器。

来自MSDN文章的引用:

  

根据Martin Fowler的说法,工作单元模式“维护一份清单   受业务事务影响的对象并协调   写出变化和解决并发问题。“