When and where to call factories at runtime?

I recently asked about the correct implementation of DI and got some links to blog posts about it. I think now I have a better understanding - the separate construction of an object from logic, placing it in factories. But all the examples are for things like websites, and are said to do all the posting at startup. Call one big factory that is new and passes everything in all the dependencies.

But what if I don't want to create everything I need? I have an object that contains a list of other objects that it can delegate, but they are expensive and are used one at a time, so I create them if necessary and let them collect when I finish. I don't want to embed new B() in logic A , because I prefer to use DI - but how? Can A call factory? It doesn't look much better unless the factory maintains state, including current dependencies. I just don't want to pass the complete list B to A when it was created, since it would be wasteful. If you want, B does not have to be inside A , although it makes logical sense ( A is the game level, B is the only screen), but in any case, the logic A determines when B is created.

So, who calls the factory to get B , and when?

Clarification: I do not use the framework for DI. I wonder if this implies the term DI?

+6
source share
2 answers

In Ninject, you can register Func<B> and query in constructor A

Autofac will automatically ship Func<B> if B already registered.

Or you can use a more direct approach and define an explicit factory for B and query factory in the constructor; its just typing as you need to create a factory for every dependency you want to lazily initialize.


Here's another SO answer that shows Ninject factory style methods: How to handle classes with static methods using Ninject?


@ Don't use the A Framework: if you can, I would probably learn it: the IoC / DI framework usually handles deferred creation for you out of the box.

If you want to continue rolling yourself, just pass the factory that creates B to your object A. Or, if you just don't like the raw Funcs and you don't want to create explicit factories for all of your objects, then you can examine Lazy<B> for more formalized decision.

+6
source

Usually two patterns are used to use rarely needed objects, which are very expensive to create. The first template uses the factory, as suggested by David Favre. The other is using a proxy.

From a design point of view, a proxy server is probably the cleanest solution, although it may take more code to implement it. This is the cleanest because the application may be completely unaware of it, because you do not need an additional interface (since you need a factory approach).

Here is a simple example with some interface and expensive implementation:

 interface IAmAService { void DoSomething(); } class ExpensiveImpl : IAmAService { private object x = [some expensive init]; void IAmAService.DoSomething() { } } 

No, you can implement a proxy server based on this interface, which may delay the creation of this implementation:

 class ServiceProxy : IAmAService { private readonly Func<IAmAService> factory; private IAmAService instance; public ServiceProxy(Func<IAmAService> factory) { this.factory = factory; } void IAmAService.DoSomething() { this.GetInstance().DoSomething(); } private IAmAService GetInstance() { // TODO: Implement double-checked lock only a single // instance may exist per ServiceProxy. if (this.instance == null) { this.instance = this.factory(); } return this.instance; } } 

This proxy class accepts the factory delegate as a dependency, just like David Fyvre described in his answer, but the application should not depend on Func<IAmAService> , but may just depend on IAmAService .

Now, instead of typing ExpensiveImpl you can enter ServiceProxy in other instances:

 // Create the proxy IAmAService service = new ServiceProxy(() => new ExpensiveImpl()); // Inject it into whatever you wish, such as: var customerService = new CustomerService(service); 
+1
source

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


All Articles