Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Optional constructor injection arguments with .NET Core

In some IoC containers it is possible to have arguments in the constructor that can't be fulfilled by the container. Is this possible with the Microsoft.Extensions.DependencyInjection libraries and IServiceProvider? If not, what is a clean solution for this sort of problem?

For example:

class InContainer
{
    public InContainer(NotInContainer dependency) { ... }
}

class Consumer
{
    public Consumer(IServiceProvider serviceProvider)
    {
         NotInContainer currentDependency = ... // from some other source
         // passing the anonymous object here is not supported, 
         // but I would like to 
         InContainer = serviceProvider.GetService<InContainer>(
             new { dependency = currentDependency }
         );
    }
}
like image 488
Daniel A. White Avatar asked Nov 03 '17 13:11

Daniel A. White


People also ask

Is it difficult to inject dependency by constructor?

Also, with constructor injection, it's easier to build immutable components. Moreover, using constructors to create object instances is more natural from the OOP standpoint. On the other hand, the main disadvantage of constructor injection is its verbosity, especially when a bean has a handful of dependencies.

When should I use IServiceProvider?

The IServiceProvider is responsible for resolving instances of types at runtime, as required by the application. These instances can be injected into other services resolved from the same dependency injection container. The ServiceProvider ensures that resolved services live for the expected lifetime.

Is AddSingleton thread safe?

Thread safety The factory method of a singleton service, such as the second argument to AddSingleton<TService>(IServiceCollection, Func<IServiceProvider,TService>), doesn't need to be thread-safe. Like a type ( static ) constructor, it's guaranteed to be called only once by a single thread.

What is IServiceCollection in .NET Core?

AddScoped(IServiceCollection, Type, Type) Adds a scoped service of the type specified in serviceType with an implementation of the type specified in implementationType to the specified IServiceCollection.


1 Answers

Normally, I create a factory by hand in this case.

public class TheFactory
{
    public TheFactory( SomeType fromContainer )
    {
        _fromContainer = fromContainer;
    }

    public IProduct Create( SomeOtherType notFromContainer ) => new TheProduct( _fromContainer, notFromContainer );

    private readonly SomeType _fromContainer;

    private class TheProduct : IProduct
    {
        // ...
    }
}

If you need per-product dependencies from the container, the factory's Create has to resolve them. Or, in the case of e.g. unity, the factory gets a Func from the container.

like image 162
Haukinger Avatar answered Sep 19 '22 10:09

Haukinger