洋葱架构中的依赖性解决方案

时间:2013-02-15 09:15:08

标签: .net asp.net-mvc dependency-injection onion-architecture

Onion Architecture是一种构建应用程序的方法,以保持关注点和松散耦合的分离(示例项目位于:http://onionarch.codeplex.com/)。依赖注入/解析是此体系结构的一个关键方面,因为它用于将所有层绑定在一起。

上面的链接包含一个关于如何使用Onion分层构建ASP.NET MVC的示例应用程序。我非常喜欢它,但是大多数这些例子都使用了Ninject(我们都知道它很慢)。我想知道是否有人可以详细说明如何将不同的DI工具(如SimpleInjector,Unity或Autofac)集成到洋葱项目中。

关键是所有层只有1个依赖项(包括MVC项目),即Core层。除了依赖关系解析图层,此图层可以引用所有图层。

我很难将MVC项目设置为启动项目,使用DI,并且不包括对MVC层中DI工具的引用。

2 个答案:

答案 0 :(得分:16)

你的问题是

  

“如何集成不同的DI工具(如SimpleInjector,Unity或   Autofac)进入洋葱项目?“

我正在使用StructureMap而不是Ninject,它的集成方式应该适用于任何其他DI框架。

正如您所说,只有依赖关系解析层应该引用所有其他层,它是您的洋葱架构的最外层。那么,为此,我创建了一个名为 BootStrapper 的项目。这是我引用StructureMap程序集的唯一项目。 在这个项目的 App_Start 文件夹中,我有一个名为 StructureMapMvc.cs 的文件,如下所示:

[assembly: WebActivator.PreApplicationStartMethod(typeof(XXXX.BootStrapper.App_Start.StructuremapMvc), "Start")]

namespace XXXX.BootStrapper.App_Start
{
    public static class StructuremapMvc
    {
        public static void Start()
        {
            IContainer container = IoC.Initialize();
            System.Web.Mvc.DependencyResolver.SetResolver(new StructureMapDependencyResolver(container));
            GlobalConfiguration.Configuration.DependencyResolver = new StructureMapHttpDependencyResolver(container);
            ControllerBuilder.Current.SetControllerFactory(new StructureMapControllerFactory());
        }
    }
}

有趣的一句是:

[assembly: WebActivator.PreApplicationStartMethod(typeof(XXXX.BootStrapper.App_Start.StructuremapMvc), "Start")]

根据金块包的描述:

  

WebActivator是一个允许其他包执行的NuGet包   Web应用程序中的一些启动代码。

非常酷,对吧?您必须做的最后一件事是确保将 BootStrapper 项目程序集推送到Web应用程序的 / bin 文件夹(使用起来很容易设置) post build动作或OutputTo nugget包)。这将避免您在MVC项目中引用 BootStrapper 项目并打破洋葱架构原则。

所以,有了这一切,它完全与Composition Root Pattern相关联,当你的应用程序启动时,模块将被组合在一起。

希望这有帮助!

答案 1 :(得分:4)

请注意,我认为Onion架构(或至少您指出的示例实现,正如@MystereMan在评论中正确指出的那样)有一个您应该注意的问题点。

尽管该体系结构似乎倾向于小型/重点接口(通常只有一个成员),但这些服务的命名似乎表明不是这样。例如,在参考架构中,有一个IShippingService类。它有一个成员,因此它遵守Interface Segregation Principle(这是好的)。但是,“送货服务”这一名称表示它应包含与送货相关的所有方法。这很容易就是几十个。但是,向此接口添加成员会破坏接口隔离原则Single Responsibility Principle(SRP)和Open Close Principle(OCP)。许多方法很少或没有关系(SRP),实现将变得庞大和丑陋。实施新的运输要求意味着添加成员,这会破坏OCP。界面有很多成员,而消费者通常只需要调用其中一个成员(低内聚力),这将使单元测试更加困难。

在与所有一个成员的接口中断开它确实解决了部分问题(并且架构可能有这个意图),但是这会留下大量的接口彼此没有关系,这使得很难将横切关注点(日志记录,监控,审计跟踪,验证,交易,容错等)应用于他们。

这是否有问题取决于很多因素,但违反其中一项SOLID原则始终需要注意。

作为洋葱架构的补充,我建议你阅读this article。它描述了这个可能的缺点的解决方案,它可以应用于洋葱架构。