汇总所有依赖项注入模块是否常见?

问题描述

我在.NET项目中使用Ninject来处理依赖项注入。

我已将我的解决方案分为多个项目:

他们精心选择了参考文献:

在应用程序的入口点初始化IoC容器似乎很常见(在我的情况下是FrontEnd)。

但是FrontEnd没有对Business Logic的引用,因此我将得到一个解决的引用错误

namespace FrontEnd
{
    class ServiceModule : NinjectModule
    {
        public override void Load()
        {
            
            this.Bind<Accountviewmodel>().ToSelf();
            this.Bind<Detailsviewmodel>().ToSelf();
            this.Bind<ISessionContext>().To<SessionContext>()
                .InSingletonScope();
            this.Bind<INavigationviewmodel>().To<Navigationviewmodel>();
            this.Bind<ILoggingService>().To<LoggingService>();
                
            // This will not work because MathClient is in the Business Logic assembly
            this.Bind<IMathProvider>().To<MathClient>()
                .Withconstructorargument("binding",new BasicHttpBinding())
                .Withconstructorargument("remoteAddress",new EndpointAddress("http://localhost/server.PHP"));

        }
    }
}

我觉得在同一位置聚合所有依赖项注入声明不是正确的选择。

我虽然要在IoC容器中声明一些静态方法,以便外部项目可以注册自己的模块,但这会使情况变得更糟,因为这将意味着BackEnd引用了FrontEnd:

namespace FrontEnd
{
    class ServiceModule : NinjectModule
    {
        public static void RegisterModule(Module m)
        {
            ...
        }
    }
}

namespace BackEnd
{
    class BackEnd
    {
        public void Init()
        {
            ServiceModule.RegisterModule(new Module() ...)
        }
    }
}

如何在我的IoC容器中配置所有服务而又没有项目之间的可疑引用(例如Backend-> FrontEnd)?

解决方法

composition root中将所有依赖项注入配置代码放在一个位置是一种常见且好的做法。

让我们假设您决定在项目之间拆分DI配置代码。实际上,这在技术上是可能的。您可以在NinjectModule程序集中创建单独的BusinessLogic。但是之后,无论如何,您都必须将此模块加载到FrontEnd程序集中。这意味着您仍然必须将FrontEnd程序集的引用添加到BusinessLogic程序集。

只需在顶级程序集中配置所有服务。如果需要向低级模块添加一些引用,请执行此操作。这比从BusinessLogic程序集向某个顶级程序集的向后引用,或从BusinessLogic程序集向DI库的引用要好得多。

请参见Mark Seemann的article。您的撰写代码应为

尽可能靠近应用程序的入口点

和:

DI容器仅应从成分根引用。所有其他模块都不应引用该容器。