norekhov
norekhov

Reputation: 4318

Autofac fails to resolve enumerable of typed HttpClients

I have a number of services which require usage of typed HttpClient from HttpClientFactory. Though I can resolve one service I can't resolve IEnumerable of this services.

interface IMyHttpClient
{
}

class MyHttpClient: IMyHttpClient
{
    public MyHttpClient(HttpClient client)
    {
    }
}

class Program
{
    static void Main(string[] args)
    {
        var services = new ServiceCollection();
        services.AddHttpClient()
                .AddHttpClient<IMyHttpClient, MyHttpClient>();

        var builder = new ContainerBuilder();
        // Exception goes away when remove this line
        builder.RegisterType<MyHttpClient>().As<IMyHttpClient>();
        builder.Populate(services);
        var provider = builder.Build();

        // ============== This works
        // provider.Resolve<IMyHttpClient>();

        // ============== This throws exception
        provider.Resolve<IEnumerable<IMyHttpClient>>();
    }
}

Constructor will be called once and than exception is thrown:

``` DependencyResolutionException: None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'ConsoleApp2.MyHttpClient' can be invoked with the available services and parameters: Cannot resolve parameter 'System.Net.Http.HttpClient client' of constructor 'Void .ctor(System.Net.Http.HttpClient)'.

```

The issue is that AddHttpClient adds it's own registration of IMyHttpClient. But I do want to register using Autofac only! Is there a way to use typed clients but still stay with Autofac?

Upvotes: 2

Views: 4231

Answers (1)

KozhevnikovDmitry
KozhevnikovDmitry

Reputation: 1720

The exception explains that Autofac can't resolve parameter 'System.Net.Http.HttpClient client'. I suppose this is because such type wasn't registered in your container for second resgistration of IMyHttpClient. To save an advantages of HttpClientFactory you can register excplicit constructor parameter for example like this:

static void Main(string[] args)
{
    var services = new ServiceCollection();
    services.AddHttpClient();

    var builder = new ContainerBuilder();
    // exclicit resolving client for constructor
    builder.RegisterType<MyHttpClient>().As<IMyHttpClient>().WithParameter(
        (p, ctx) => p.ParameterType == typeof(HttpClient), 
        (p, ctx) => ctx.Resolve<IHttpClientFactory>().CreateClient());

    builder.Populate(services);
    var provider = builder.Build();

    // ============== This works
    provider.Resolve<IMyHttpClient>();

    // ============== This works too
    provider.Resolve<IEnumerable<IMyHttpClient>>();
}

In this example Resolve<IEnumerable<IMyHttpClient>> return enumeration with single IMyHttpClient, that is initialized with HttpClient from core HttpClientFactory.

UPD: the post was updated by @norekhov comment

Upvotes: 6

Related Questions