Can I use an IoC container to create a dependency that requires a runtime value?

I am new to IoC, so I wonder if this is really the right tool for the job I want to do.

I am writing a multi-user application, and there are several places that may be required to use various interface implementations based on the organization to which the current input user belongs.

Say, for example, when a user from one organization creates a work order, an email must be sent to this user manager. But for all other organizations, this letter does not need to be sent. Classic strategy template.

My question is: can I somehow instruct the IoC container to view a specific runtime value (user OrganizationId in this case) to determine which implementation of IWorkOrderProcessor to insert into the constructor the object that needs it?

I am currently using Windsor, but examples using other containers will be fine.

+4
source share
4 answers

Windsor has an extension point that is ideal for multi-tenant applications: IHandlerSelector.

This allows you to encode your application as if it were not multi-user. Multiuser logic is carried over from your business logic.

+3
source

The best containers for IOC will support this use.

I am not familiar with Windsor; my choice for IOC is StructureMap. In the free StructureMap interface, you have many options for adjusting the input parameters of objects in runtime, depending on what you can express in the code. I am sure that Windsor offers the same.

The only thing I’m talking about using IOC is that someday it will really make it difficult to understand the solution.

In your example, if you really have the right use case for a strategy template in which you would implement this behavior, even if you would not use IOC as an input strategy object (using some Factory approach), then I would say yes continue the implementation of the IOC.

But if you really don't need to introduce an abstraction of the whole object to express the logic of whether certain users receive emails, this might be the case for templates for templates.

+1
source

I think you can, because an IoC container can use different types of injections:

  • constructor injection
  • setter injection
  • interface injection (injection method)

Entering the constructor gives a fully initialized object, but the types and values ​​that you enter must be known immediately before creating the object (for example, they can be loaded from the configuration file).

Injecting a method (or setter) is flexible - you can delay the injection until you get the type or value you want. The disadvantage of this approach is that you do not have a fully initialized object when you create it.

It all depends on how your container is implemented.

By the way, similar questions were asked: IoC: Existing runtime objects, not container-initialized prerequisites for components
0
source

This is a common problem with DI, and the answer is always to create and introduce an Abstract Factory . In your case, you can define an interface like this:

 public interface IWorkerProcessorFactory { IWorkerProcessor Create(int organizationId); } 

In all classes where you have an organization identifier and need an instance of IWorkerProcessor, you depend on IWorkerProcessorFactory and call its Create method.

This template works with Poor Man DI or just with any DI container that you would like to use.

Here is a more complete example: Cannot combine Factory / DI

0
source

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


All Articles