Using Unity instead of ASP.Net Core DI IServiceCollection
Asked Answered
C

2

9

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?

Causeway answered 5/6, 2018 at 17:28 Comment(2)
Well, as you said, the two concrete types you are looking to use are internal, so that's that, you can't directly use them. Just wanted to add a thought: can you set up your Unity IOC so that it resolves IHttpClientFactory by in turn resolving IHttpClientFactory from the ASP.NET IServiceCollection?Taliped
I resolved this issue by using unity adapter for IServiceCollection: https://mcmap.net/q/1132300/-using-unity-instead-of-asp-net-core-di-iservicecollectionCauseway
C
15

Edit 7.12.2022: Unity is now deprecated, so do not use it for new projects. I replaced it with Autofac.

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());

        }

    }
}
Causeway answered 26/6, 2018 at 7:10 Comment(3)
Note: in case of a very minimal .csproj, the full DependencyInjection dependency might be missing. I had to add it with <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="2.2.0" />.Hanhhank
This doesn't work for me. ServiceCollection seems to come from Microsoft.Extensions.DependencyInjection, but I do not see a using in your example for this. It isn't found in Unity's package. Also there's no AddHttpClient() method, so I'm not sure where that's coming from.Presber
@Presber Everything that you are missing is in usings directive. Check if you have appropriate NuGet packages (their version will be higher now).Causeway
A
7

You have 2 options:

Aranda answered 6/6, 2018 at 7:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.