Search code examples
c#asp.netninjectonion-architecture

Set Scope for Ninject Modules in Onion Architecture


I have multiple Projects in Visual Studio with a Ninject-Moduledefinition for each assembly. This Solution is structured as "Onion Architecture". The Modules are loaded only in the Projects with references to the assembly.

I have these Layers

  • Repository
  • BusinessLayer
  • Web-UI

At the moment the Web-UI - Layer doesn't need to reference the repository, because the Ninject-Moduleloader of the BusinessLayer get's all referenced bindings from the Repository-Moduleloader

My Repository-Layer doesn't have any reference to ASP.Net assemblies. So I can't set the scope of my NinjectModules to "InRequestScope". I am trying now to set the configuration of the ModuleLoader in my WebUI-Layer, but the Modules of the repository are still not "InRequestScope"

private static void RegisterServices(IKernel kernel) {           
    kernel.Bind(i => i.From("*.dll")
    .SelectAllClasses()
    .BindDefaultInterface()
    .Configure(x => x.InRequestScope()));

    kernel.Load(new BusinessLayer.BusinessLayerModuleLoader());
    kernel.Load(new WebUIInjector());
}
  1. Why is this configuration not working with modules, loaded by BusinessLayerModuleLoader itself?
  2. is the first statement only binding the configuration, or does it load the NinjectModules from all assemblies found by "*.dll" already? In that case I wouldn't need the second statement "kernel.Load(new BusinessLayer..." right?

Solution

  • The first statement (kernel.Bind(i => i.From(....));) is searching all deployed *.dll's for types which have an interface matching the "default interface" convention, which is: Typename ends in interface name (without the leading I), for example: "Foo --> IFoo", "Bar --> IBar", "SomeFoo : IFoo". It does not load any modules.

    Kernel.Load runs the Load method of a NinjectModule which can add additional bindings. The preferred alternative would be to use kernel.Load<BusinessLayer.BusinessLayerModuleLoader>() and to name it BusinessLayerModule instead of BusinessLayerModuleLoader.

    To load all the modules of all deployed dlls run: kernel.Load("*.dll");. For more information on modules and module loading see: https://github.com/ninject/Ninject/wiki/Modules-and-the-Kernel

    Note: If a module were to do Bind<IFoo>().To<Foo>() there would be 2 bindings for IFoo as the convention already bound it. This would result in an NinjectActivationException with message ...more than one matching binding available....

    Hint: The question of how to parameterize scopes applied in NinjectModules has been asked on SO before.