1

I'm using Ninject in a .NET project to handle dependency injection.

I have divided my solution into multiple projects :

  • Business Logic
  • FrontEnd
  • ViewModels

They have carefully selected references :

  • FrontEnd has a reference to ViewModels
  • ViewModels has a reference to BusinessLogic

It seems common to initialize the IoC container in the entrypoint of the application (in my case this is the FrontEnd).

But FrontEnd doesn't have a reference to Business Logic, so I'll get an unresolved reference error.

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

        }
    }
}

I feel like aggregating all the dependency injection declaration in the same place isn't the right thing to do.

I though about declaring some static method in the IoC container so that external projects can register their own modules, but that would make things even worse, because it would mean BackEnd has a reference to the FrontEnd :

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

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

How can I configure all my services into my IoC container without having suspicious references between projects (like Backend -> FrontEnd) ?

Arthur Attout
  • 2,701
  • 2
  • 26
  • 49
  • 1
    Duplicate: https://stackoverflow.com/questions/9501604/ioc-di-why-do-i-have-to-reference-all-layers-assemblies-in-applications-entry – Steven Oct 02 '20 at 14:17

1 Answers1

1

It is a common and good practice to have all of your dependency injection configuration code in one place, in the composition root.

Let's imagine that you decide to split your DI configuration code between projects. Actually, it is technically possible. You can create a separate NinjectModule in your BusinessLogic assembly. But after that, you have to load this module in your FrontEnd assembly anyway. It means that you still have to add a reference from FrontEnd assembly to BusinessLogic assembly.

Just configure all services in a top-level assembly. If you need to add some references to low-level modules, do it. It is much better than having a backward reference from the BusinessLogic assembly to some top-level assembly or having a reference from your BusinessLogic assembly to a DI-library.

See this article of Mark Seemann. Your composition code should be

as close as possible to the application's entry point

and:

A DI Container should only be referenced from the Composition Root. All other modules should have no reference to the container.