Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Unity instead of ASP.Net Core DI IServiceCollection

More and more .NET Core libraries is bound to IServiceCollection. In example, I want to use HttpClientFactory described here in my NET Framework 4.7.1. desktop application. My application is using Unity IoC. I referenced Microsoft.Extensions.Http as NuGet.

But there is a problem: new ASP.Net Core components are bound to Microsoft DI framework for .NetCore - IServiceCollection. In example, registration of HttpClientFactory is here:

public void ConfigureServices(IServiceCollection services)
{
    services.AddHttpClient();
}

I was going deeper into MS code and wanted to manually register corresponding interfaces and classes to Unity. This is how services are registered by IServiceCollection:

services.TryAddTransient<HttpMessageHandlerBuilder, DefaultHttpMessageHandlerBuilder>();
services.TryAddSingleton<IHttpClientFactory, DefaultHttpClientFactory>();

This would be no problem to move this to Unity IoC, but I am stucked when I want to register DefaultHttpMessageHandlerBuilder and DefaultHttpClientFactory which have internal visibility. So they are not available for registration outside of MS code.

Do I have any chance how to resolve this situation?

like image 550
Karel Kral Avatar asked Jun 05 '18 17:06

Karel Kral


2 Answers

Based on @davidfowl answer, I have used his second solution and completed code:

These packages need to be referenced from my project (snippet from .csproj):

 <ItemGroup>
    <PackageReference Include="Microsoft.Extensions.Http">
      <Version>2.1.1</Version>
    </PackageReference>
    <PackageReference Include="Unity.Microsoft.DependencyInjection">
      <Version>2.0.10</Version>
    </PackageReference>
  </ItemGroup>

And here is the test that services from ServiceCollection can be resolved from Unity container:

using System;
using System.Linq;
using System.Net.Http;
using Microsoft.Extensions.DependencyInjection;
using Unity;
using Unity.Microsoft.DependencyInjection;
using Xunit;

namespace FunctionalTests
{
    public class UnityWithHttpClientFactoryTest
    {

        /// <summary>
        /// Integration of Unity container with MS ServiceCollection test
        /// </summary>
        [Fact]
        public void HttpClientCanBeCreatedByUnity()
        {
            UnityContainer unityContainer = new UnityContainer();

            ServiceCollection serviceCollection = new ServiceCollection();
            serviceCollection.AddHttpClient("Google", (c) =>
            {
                c.BaseAddress = new Uri("https://google.com/");
            });
            serviceCollection.BuildServiceProvider(unityContainer);

            Assert.True(unityContainer.IsRegistered<IHttpClientFactory>());
            IHttpClientFactory clientFactory = unityContainer.Resolve<IHttpClientFactory>();
            HttpClient httpClient = clientFactory.CreateClient("Google");

            Assert.NotNull(httpClient);
            Assert.Equal("https://google.com/", httpClient.BaseAddress.ToString());

        }

    }
}
like image 200
Karel Kral Avatar answered Sep 22 '22 12:09

Karel Kral


You have 2 options:

  • Create a ServiceCollection, add the factory and then call BuildServiceProvider and resolve the IHttpClientFactory. There's an uber sample here https://github.com/aspnet/HttpClientFactory/blob/64ed5889635b07b61923ed5fd9c8b69c997deac0/samples/HttpClientFactorySample/Program.cs#L21.

  • Use the unity adapter for IServiceCollection https://www.nuget.org/packages/Unity.Microsoft.DependencyInjection/.

like image 25
davidfowl Avatar answered Sep 18 '22 12:09

davidfowl