Search code examples
c#dependency-injectionioc-containerninject-2

How to keep IoC container in one place, while inner classes need to create dependencies after beeing constructed


I started to use Ninject , on this relatively small project and i have run into a problem: i have this class

class SomeService : ISomeService 

that depends on

class BizLogicModule : IBizLogicModule

that in turn depends on

class DataRepository : IDataRepository

the DataRepository has a ctor that looks like:

DataRepository(BizEntityModel context)

Now, i need to be able to use a single instance of BizEntityModel across more than one IDataRepository instance.
I also need to create IDataRepository's along the life of a IBizLogicModule. The IBizLogicModule does not know about Ninject and i want to keep it that way.

so my problem is: how to wire all that up, using the Ninject kernel, while:

  1. not having to pass the kernel instance around the layers.

  2. leaving the code readable close to what it was prior Ninject (i was just new'ing using a factory method).

The simple part of the wiring i got so far is:

Bind<SomeService>().To<ISomeService>();
Bind<BizLogicModule>().To<IBizLogicModule>();
Bind<DataRepository>().To<IDataRepository>(); 
Bind<BizEntityModel>().To<BizEntityModel>(); //ToSelf()
// .WithConstructorArgument(context => Kernel.Get<BizEntityModel>)

Your guidance is very much appreciated

EDIT: Thanks for your answers!
here's some more data that was requested: BizEntityModel is registered with Ninject (code updated).

if i understand correctly: i can create instances of IDataRepository in IBizLogicModule using a 'factory method'. but that leaves me with:
1) i need to pass a BizEntityModel to the factory method, some times its bran new and sometimes its an existing instance. using the factory method, it will create anew one every time.
2) is this a problem that SomeService is in another assembly, and only it has a ref to Ninject.dll ?


Solution

  • Do you register BizEntityModel with Ninject? If so, you should be able to tell Ninject to supply one and only one instance of a BizEntityModel for every request for the lifetime of the container, or even the program, without having to define and register a traditional singleton instance of BizEntityModel. Even if you have to work with a factory method and Ninject won't let you singleton-scope that registraion, if you have to you can eager-load the object and then register the instance for the dependency as a singleton.

    IBizLogicModule should never have to know about Ninject; Ninject should know about BizLogicModule. Try creating an IDataRepository registration that will provide a factory method (factory-scoped so a new instance is created per call), then pass that factory method as a dependency to IBizLogicModule, which will use it when it needs to create IDataRepositories. You're basically passing through the IoC's resolution capabilities to provide a factory class in IBizLogicModule. If you do that for a lot of different class types on IBizLogicModule, you're basically creating a service locator which I would personally avoid, but one or two is a perfectly valid Factory/Creator pattern.