I undertook implementation of IoC for data service. I did this:

interface IDataService { } 

and its implementation (take for example RpcJson):

 class JsonRpcDataService : IDataService { } 

Then we register them in the IoC container. It's all clear for now.

Next, go to the actual implementation. I defined the following data service structure:

  1. Models - everything is clear
  2. Collectors are helper classes for getting data
  3. Handlers - helper classes for data processing (save, for example)

We describe the model interface:

 interface IBook { string Autor { get; set; } ... } 

Collector:

 interface IBooksCollector { IEnumerable<IBook> GetItems(); ... } 

And the handler:

 interface IBooksHandler { void Save(IBook book); ... } 

Well and, respectively, for we realize each of them for JsonRpc. Next, we supplement the IDataService interface:

 interface IDataService { IBook CreateBook(); IBooksCollector CreateBooksCollector(); IBooksHandler CreateBooksHandler(); } 

And we implement these methods in JsonRpcDataService . I made them so that I, at the ViewModel level, should only associate IDataService with RpcJsonDataService, and not all interfaces with their implementations. So that in the end I could do something like this:

 var dataService = IoC.Resolve<IDataService>(); // Создаем модель IBook book = dataService.CreateBook(); 

Instead

 IBook book = IoC.Resolve<IBook>(); 

and somewhere before binding

 IBook book = IoC.Register<IBook, Book>(); 

where Book is an IBook implementation for RpcJson . Since there can be a lot of models, instead of a heap of lines of the form:

 IoC.Register<IModel, ModelClass>(); 

It all comes down to one thing:

 IoC.Register<IDataService, RpcJsonDataService>(); 

Along the way I had questions that I ask you to answer:

  1. Is this approach correct with creating instances? Or can it make a factory of the form CreateModel<T>() , into which the interface will be passed as a parameter T , and the factory will already decide what to "give"?
  2. Is it worth making interfaces for models at all, or is it better to describe them right away? I [JsonProperty(...)] them in order not to clutter up with attributes of the form [JsonProperty(...)] , necessary for serialization, because these attributes are needed only for the RpcJson server
  • one
    If there are a lot of models, then the IDataService class will swell, and instead of a heap of strings with type registration in the container, there will be one very large class. I think the answer to the first question: no, not correctly, when using a container, it will fulfill the role of a factory that "will decide what to give." - cybrex
  • 3
    I also highly recommend the book "Siman M. - Deploying dependencies in .NET". It is very intelligible and explains the introduction of dependencies with examples. - cybrex
  • @cybrex, if there are a lot of them, you can make separate factories for models, collectors and processors. Just with this approach, I register one dependency, and if you register all dependencies, it is expensive - Donil
  • Do not quite understand why it is expensive? Because a lot of the same type of registration code? Surely the registration can be transferred to an XML file, most containers support it. - cybrex
  • 2
    Also, there is auto type registration . Perhaps the link is not very successful, but an example for a specific container can be google. - cybrex 1:31 pm

1 answer 1

First of all, your desire to do with the minimum number of component registrations is incorrect. If you have 40 components there is nothing wrong with registering all 40 components in a container. This will not be a mistake. Moreover, although many containers support automatic registration of components in one form or another, Castle Windsor, for example, as far as I know, requires you to explicitly register each component, and this approach with explicit registration has a definite meaning. But here you have the right to choose what is closer to you - automatic registration or explicit registration of each component, both approaches have their own advantages and disadvantages.

The second is that you mistakenly associate the registration of a component and then receive it from the container. If you wrote IoC.Register<IComponent, Component>(); This does not mean that you must get it from the container later to receive the IComponent . As a rule, you register n - components, but from the IoC container - you request only one. For example, if you have an ASP-MVC application, it may have many components (controllers, services, etc.), but you will only have one component request from the IoC container - this will be the controller request in the controller factory. To understand why register 10 components, if only 1 will be requested, read about the main patterns of dependency injection - the introduction of the constructor and the implementation of the property .

Answers to your questions:

  1. Using factories to create models is a normal approach. To create a factory method of the form CreateModel<T>() where T is the interface of the model does not make sense. Think about how this method will be fundamentally different from the analogous method of an IoC container?
  2. Most likely you should not do interfaces for models. Using an IoC container does not necessarily oblige you to create interfaces for each class in your application. For models, interfaces are most often not needed.

By the wording of your question, you can see that you are rather poorly oriented in the subject and are moving in the wrong direction. You should spend some time studying it before designing the application. In particular, the dependency injection patterns mentioned above ( constructor embedding and property embedding ) are more important for understanding DI than any issues related to registering components in an IoC container. In general, dependency injection is just about these patterns, and an IoC container is just a tool that facilitates building an application using DI, and DI can be used without an IoC container at all.

In the comments @cybrex advised to read the book Siman M. - Dependency Injection in .NET . I am attached to this advice, read - you will not regret.

  • @Donil Corrected the answer - changed the answer to the first question - Andrew Prigorshnev
  • Thanks for the detailed answer! Yes, really, I am guided while badly. Interfaces I have allocated for them to be. so to speak, "clean", so as not to clutter them, as I already wrote, with attributes of the form JsonProperty. Just now I have one provider - JsonRpc and one attribute on the field, for serializing / deserializing json. And if there is one more? Say XmlRpc, then attributes will appear for serializing / deserizing XML. And so each provider has its own implementation of models with its own, necessary only for it, attribute set - Donil
  • @Donil means interfaces are needed, but again you don’t have to register them in the IoC container. For example, your models may implement interfaces from the IDisposable or ICloneable framework, but you will not register these interfaces in a container because of this. Similarly, your code can have your own interfaces that are not component interfaces and are not registered in the IoC container. - Andrew Prigorshnev
  • I understand this (about IDisposable and ICloneable ). But if I have a ViewModel, with a BookVM(IBook) view constructor, then the IBook model IBook needs to be registered, right? I may need to create a new book. - Donil 2:21 pm
  • And what will you do when you need to create a new book? Call IoC.Resolve<IBook>(); ? - Andrew Prigorshnev