Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Covariant service resolution by IoC container

I'm using dependency injection pattern for my application without any IoC Container. Now I decided to use some IoC Container because my Composition Root consists of thousands lines of code, but I failed to make it work with my classes, which actively use variance. For example the following interface

public interface IQuery<in TIn, out TOut>
{
    IReadOnlyCollection<TOut> Get(TIn key);
}

and service

public class FakeRepository : IQuery<object, string>
{
    public IReadOnlyCollection<string> Get(object key)
    {
        return new[] { key.ToString() };
    }
}

Pure DI works fine

IQuery<string, object> service = new FakeRepository();

But neither Autofac nor DryIoc can resolve it.

service = autofacContainer.Resolve<IQuery<string, object>>(); // exception
service = dryIocContainer.Resolve<IQuery<string, object>>(); // exception

Do I need some additional setup? Is there any other IoC container that support this? Am I asking too much?

The full code: https://dotnetfiddle.net/vlw17R

like image 403
Andrey Avatar asked Jan 17 '18 13:01

Andrey


People also ask

Which IoC container is best?

You can waste days evaluating IOC containers. The top ones are quite similar. There is not much in this, but the best ones are StructureMap and AutoFac. At SSW we use Autofac on most projects.

What IoC container?

IoC container is a framework for implementing automated dependency injection. It contains object creation for the longer ways to use and injects dependencies within the class.

What is IoC container in Spring?

Spring IoC Container is the core of Spring Framework. It creates the objects, configures and assembles their dependencies, manages their entire life cycle. The Container uses Dependency Injection(DI) to manage the components that make up the application.

What is IoC container in asp net core?

ASP.NET Core contains a built-in dependency injection mechanism. In the Startup. cs file, there is a method called ConfigureServices which registers all application services in the IServiceCollection parameter. The collection is managed by the Microsoft.


1 Answers

It won't work in current DryIoc versions (stable v2.12.6 and preview v3.0.0-preview-03).

But nothing in theory prevents the registering of open-generic service type with closed or non-generic implementation type.

For the single service-to-implementation registration:

container.Register(typeof(IQuery<,>), typeof(FakeRepository));

DryIoc will throw the exception because of the internal check for implemented types. If I adjust the check to include open-generic version of service type, then this works:

container.Resolve<IQuery<string, object>>();

The similar adjustment may be done to include open-generic service types in RegisterMany.

But the remaining issue will be with ResolveMany. It is rather an implementation detail, but having both closed and open-generic versions of services may produce two instances when resolving a collection.

Concluding, I have created an issue in DryIoc tracker, and will think how to enable this in a safe manner.

Update

The new DryIoc v2.12.7 is released with Register capable of registering the open-generic service type. But not the RegisterMany. Check the issue for more details.

like image 146
dadhi Avatar answered Sep 29 '22 17:09

dadhi