Использование Unity вместо ASP.Net Core DI IServiceCollection

Karel Kral спросил: 12 мая 2018 в 03:48 в: c#

Все больше и больше библиотек .NET Core привязаны к IServiceCollection. В качестве примера я хочу использовать HttpClientFactory, описанный здесь, в моей .NET Framework 4.7.1. настольного приложения. Мое приложение использует Unity IoC. Я ссылался на Microsoft.Extensions.Http как на NuGet.

Но есть проблема: новые компоненты ASP.Net Core привязаны к инфраструктуре Microsoft DI для .NetCore - IServiceCollection. Например, регистрация HttpClientFactory находится здесь:

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

Я шел глубже в код MS и хотел вручную зарегистрировать соответствующие интерфейсы и классы для Unity. Вот как службы регистрируются в IServiceCollection:

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

Это не проблема, чтобы переместить это в Unity IoC, но я застреваю, когда хочу зарегистрировать DefaultHttpMessageHandlerBuilder и DefaultHttpClientFactory, которые имеют видимость internal. Таким образом, они недоступны для регистрации вне кода MS.

Есть ли у меня шанс решить эту проблему?


2 ответа

Есть решение
davidfowl ответил: 12 мая 2018 в 05:21

У вас есть 2 варианта:

  • Создайте ServiceCollection, добавьте фабрику, а затем вызовите BuildServiceProvider и разрешите IHttpClientFactory. Здесь есть образец uber. Https://github.com/aspnet/HttpClientFactory/blob/64ed5889635b07b61923ed5fd9c8b69c997deac0/samples/HttpClientFactorySample/Program.cs#L21.

  • Используйте адаптер единства для IServiceCollection https://www.nuget.org/packages/Unity.Microsoft.DependencyInjection/.

Karel Kral ответил: 01 июня 2018 в 05:30

Основываясь на ответе @davidfowl, я использовал его второе решение и код:

Эти пакеты должны ссылаться на мой проект (фрагмент из .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>

И вот тест, который сервисы из ServiceCollection можно разрешить из контейнера Unity:

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