4

So, I've been reading about CQRS while deciding about architecture for my project and found this library. It's not very complex or anything like that but one thing caught my eye: here the ISeviceProvider is being injected and here it is being used. So, my question: is it a good practice to build objects with service provider directly, meaning without the injecting? If not which would be the correct way to build objects if the type of object will be known only in runtime?

2 Answers 2

3

Using IServiceProvider is basically the only option for DI (e.g. via RequestServices in MVC components) if you only know the type at run-time.

Constructor injection is only viable if you already know the type at compile-time, because you must specify the type of the object in the constructor.

Depending on the need, you can also register an implementation factory in ConfigureServices(), and give out different instances of some interface depending on runtime information.

EDIT: An example of an implementation factory in ASP.NET Core:

services.AddTransient<IDataService, DataService>((ctx) =>
{
    IOtherService svc = ctx.GetService<IOtherService>();
    //IOtherService svc = ctx.GetRequiredService<IOtherService>();
    return new DataService(svc);
});

Here DataService depends on IOtherService, so it gets it from the service provider with GetService<T>(). You can use GetRequiredService<T>() to enforce the requirement.

Sign up to request clarification or add additional context in comments.

4 Comments

agree, but factory won't let you inject anything into objects you build unless you manually create dependency but then you loose the advantage of dependency injection built-in framework
True, though in the factory you can request dependencies from the container so it's not entirely manual.
what do you mean? could you provide an example for that? are you talking that factory receives the service provider or am I missing somethig?
Added an example :)
3

is it a good practice to build objects with service provider directly, meaning without the injecting?

It depends. Injecting a generic resolver into a class instead of specific dependencies is a pattern generally referred to as Service Locator and it is considered to be an anti-pattern.

Whether or not the use of this IServiceProvider is an implementation of the Service Locator anti-pattern however, depends on how it is used, as explained here:

A DI container encapsulated in a Composition Root is not a Service Locator - it's an infrastructure component.

We can consider this CommandProcessor to be a piece of infrastructure, as long as it is "encapsulated in a Composition Root".

2 Comments

but Only applications should have Composition Roots. Libraries and frameworks shouldn't
@arthur.borisow: that's correct. the CommandProcessor should be part of the start up project. You should certainly not place the ICommand and ICommandHandler<T> abstractions and CommandProcessor implementation in the same project.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.