How to register and resolve open generic with two type arguments as interface with one type argument using Autofac

1.8k views Asked by At

Problem

I have a number of concrete, generic classes with two type arguments that implement a generic interface with one type argument. For example:

public interface ISomeService<T>
{
    // ...
}

public class SomeService<TA, TB> : ISomeService<TA>
{
    // ...
}

I register them using Autofac like this:

var containerBuilder = new ContainerBuilder();

containerBuilder.RegisterGeneric(typeof(SomeService<,>))
    .As(typeof(ISomeService<>))
    .InstancePerLifetimeScope();

var container = containerBuilder.Build();

When attempting to resolve an instance of ISomeService<Foo> like this:

var service = container.Resolve<ISomeService<Foo>>();

I get an Autofac.Core.Registration.ComponentNotRegisteredException exception saying that the requested service ISomeService`1[[Foo]] has not been registered.

Questions

  1. Is what I'm trying to do impossible using Autofac?
  2. If so, is there a workaround?
  3. If not, do other DI containers offer such a capability, e.g. SimpleInjector?
1

There are 1 answers

1
Steven On

With Simple Injector, you can make register a partially-closed generic type as follows:

container.Register(typeof(ISomeService<>),
    typeof(SomeService<,>).MakeGenericType(
        typeof(SomeService<,>).GetGenericArguments().First(),
        typeof(Bar)),
    Lifestyle.Scoped);

There is no other DI library that can handle this, but in this case there is a simple workaround for containers like Autofac; you can simply derive from the type:

public class BarSomeService<TA> : SomeService<TA, Bar>
{
    public BarSomeService([dependencies]) : base([dependencies]) { }
}

containerBuilder.RegisterGeneric(typeof(BarSomeService<>))
    .As(typeof(ISomeService<>))
    .InstancePerLifetimeScope();