Can't figure out ninject (or just the IOC container as a whole) through factory DI?

Ok, so I read in ninject recently, but I had trouble understanding what makes it better, why they link to the "poor person" DI page on the wiki page. The sad thing is that I looked at all their pages on the wiki and still do not understand = (.

I usually port classes of service to a factory template that processes DI like this:

public static class SomeTypeServiceFactory { public static SomeTypeService GetService() { SomeTypeRepository someTypeRepository = new SomeTypeRepository(); return = new SomeTypeService(someTypeRepository); } } 

Which seems very similar to modules to me:

 public class WarriorModule : NinjectModule { public override void Load() { Bind<IWeapon>().To<Sword>(); Bind<Samurai>().ToSelf().InSingletonScope(); } } 

If each class has a module associated with it, and you bind its constructor to a specific implementation. While ninject code is 1 line, I just don't see this advantage. Anytime you add / remove constructors or change the implementation of an interface constructor, will you have to change the module in much the same way as in the factory? Therefore, we do not see the benefits here.

Then I thought that I could come up with a general factory-based conditional contract as follows:

  public static TServiceClass GetService<TServiceClass>() where TServiceClass : class { TServiceClass serviceClass = null; string repositoryName = typeof(TServiceClass).ToString().Replace("Service", "Repository"); Type repositoryType = Type.GetType(repositoryName); if (repositoryType != null) { object repository = Activator.CreateInstance(repositoryType); serviceClass = (TServiceClass)Activator.CreateInstance(typeof (TServiceClass), new[]{repository}); } return serviceClass; } 

However, this is crappy for two reasons: 1) it is highly dependent on a naming convention; 2) he suggested that there will never be any constructors in the repository (not true), and that the only repo constructor will be this corresponding repo (also not true). I was told: "Hey, this is where you should use the IoC container, it would be great here!" And so, my research has begun ... but I just don't see it, and it's hard for me to understand this ...

Is there any way that ninject can automatically resolve class constructors without a special declaration, so it would be great to use it in my universal factory (I also understand that I could just do it manually using reflection, but that would hit performance and ninject says right on their page that they don’t use reflection).

Read this problem and / or show how it can be used in my general factory!

EDIT: answer

Thus, thanks to the explanation below, I skillfully fully understood the awesomeness of ninject, and my overall factory is as follows:

 public static class EntityServiceFactory { public static TServiceClass GetService<TServiceClass>() where TServiceClass : class { IKernel kernel = new StandardKernel(); return kernel.Get<TServiceClass>(); } } 

Pretty awesome. Everything is handled automatically, since specific classes have implicit binding.

+6
source share
2 answers

The benefits of IoC containers grow with project size. For small projects, their advantage over the β€œPoor Man,” like your factory, is minimal. Imagine a large project in which there are thousands of classes, and some services are used in many classes. In this case, you only need to say how these services will be allowed. In the factory, you need to do this over and over for each class.

Example. If you have a MyService : IMyService and a class A that requires IMyService , you must tell Ninject how it should resolve these types, as in your factory. Here the advantage is minimal. But once you start the project, you add a class B , which also depends on IMyService , you just need to tell Ninject how to resolve B Ninject already knows how to get IMyService . In factory, on the other hand, you need to determine again how B gets its IMyService .

To take it one step further. You should not define bindings one by one in most cases. Use conditional configuration ( Ninject.Extension.Conventions ) Ninject.Extension.Conventions . With this, you can group classes together (Services, Repositories, Controllers, Presenters, Views, ....) and configure them the same way. For instance. tell Ninject that all classes that end with the Service must be single and publish all their interfaces. This way you have one configuration and no changes are required when adding another service.

Also, IoC containers are not just factories. There are many more. For instance. Lifecycle Management, Interception, ....

 kernel.Bind( x => x.FromThisAssembly() .SelectAllClasses() .InNamespace("Services") .BindToAllInterfaces() .Configure(b => b.InSingletonScope())); kernel.Bind( x => x.FromThisAssembly() .SelectAllClasses() .InNamespace("Repositories") .BindToAllInterfaces()); 
+7
source

To be completely analog, your factory code should read:

 public static class SomeTypeServiceFactory { public static ISomeTypeService GetService() { SomeTypeRepository someTypeRepository = new SomeTypeRepository(); // Somewhere in here I need to figure out if i'm in testing mode // and i have to do this in a scope which is not in the setup of my // unit tests return new SomeTypeService(someTypeRepository); } private static ISomeTypeService GetServiceForTesting() { SomeTypeRepository someTypeRepository = new SomeTypeRepository(); return new SomeTestingTypeService(someTypeRepository); } } 

And the equal in Ninject will be:

 public class WarriorModule : NinjectModule { public override void Load() { Bind<ISomeTypeService>().To<SomeTypeService>(); } } public class TestingWarriorModule : NinjectModule { public override void Load() { Bind<ISomeTypeService>().To<SomeTestingTypeService>(); } } 

Here you can define dependencies declaratively, ensuring that the only differences between your test and production code are contained in the setup phase.

The advantage of IoC is not that you do not need to change a module every time an interface or constructor changes, it is a fact that you can declare dependencies declaratively and that you can plug and play different modules for different purposes.

+2
source

Source: https://habr.com/ru/post/906955/


All Articles