Xamarin.Forms (DryIoc.Microsoft.DependencyInjection) Prism 上的 DryIoc 和 IServiceProvider

DryIoc and IServiceProvider on Prism for Xamarin.Forms (DryIoc.Microsoft.DependencyInjection)

我有一个以 DryIoc 作为容器的 Prism 应用程序。 我想 IHttpClientFactory 向我的 类型的客户 提供 HttpClient,它们是这样的:

public class ExampleService : IExampleService
{
    private readonly HttpClient _httpClient;

    public RepoService(HttpClient client)
    {
        _httpClient = client;
    }

    public async Task<IEnumerable<string>> GetExamplesAsync()
    {
        // Code deleted for brevity.
    }
}

App.xaml.cs 中,我注册了我的类型化客户端,以便它们可以通过以下方式注入到视图模型中:

public partial class App

// ...

protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
    // Code deleted for brevity.
    containerRegistry.Register<IExampleService, ExampleService>();
}

那是在尝试使用 IHttpClientFactory 之前。

现在,要添加它,我们 should AddHttpClient() IServiceCollection。那就是我认为需要 DryIoc.Microsoft.DependencyInjection 的地方,所以,仍然在 App.xaml.cs 中,我写了以下内容:

public partial class App

// ...

protected override IContainerExtension CreateContainerExtension()
{
    var services = new ServiceCollection();

    services.AddHttpClient<IExampleService, ExampleService>(c =>
    {
        c.BaseAddress = new Uri("https://api.example.com/");
    });

    var container = new Container(CreateContainerRules())
        .WithDependencyInjectionAdapter(services);

    return new DryIocContainerExtension(container);
}

问题是,在我的 ExampleService 中,我得到的 client 具有以下规格:

{
   "DefaultRequestHeaders":[
   ],
   "BaseAddress":null,
   "Timeout":"00:01:40",
   "MaxResponseContentBufferSize":2147483647
}

而我预计 BaseAddresshttps://api.example.com/,因此 REST API 调用失败。

将 Prism for Xamarin.Forms 与 DryIoc 一起使用时,IServiceProvider 的正确模式是什么?不幸的是,没有关于以下问题的文档或开源代码,我有点迷茫。

谢谢你,祝你有美好的一天。

更新 #1

按种类Dan S. guidance, DryIoc.Microsoft.DependencyInjection was uninstalled so the project came back at its state before trying to use IServiceCollection dependencies (in my case, IHttpClientFactory), then I installed Prism.Forms.Extended and later Prism.DryIoc.Extensions.
之后 CreateContainerExtension()App.xaml.cs 变成:

protected override IContainerExtension CreateContainerExtension()
{
    var containerExtension = PrismContainerExtension.Current;
    containerExtension.RegisterServices(s =>
    {
        s.AddHttpClient<IExampleService, ExampleService>(c =>
        {
            c.BaseAddress = new Uri("https://api.example.com/");
        });
    });
    return containerExtension;
}

containerRegistry.Register<IExampleService, ExampleService>(); 已从 RegisterTypes() 中删除。

现在 ExampleService 终于注入了 HttpClient 并且一切正常。

更新 #2

我正在使用的与 Prism 相关的唯一软件包是 Prism.DryIoc.Forms and Prism.DryIoc.Extensions。 我在 App.xaml.cs 中完全删除了 CreateContainerExtension() 的覆盖并重构了 RegisterTypes()

protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
    // Code deleted for brevity.
    containerRegistry.RegisterServices(s =>
    {
        s.AddHttpClient<IExampleService, ExampleService>(c =>
        {
            c.BaseAddress = new Uri("https://api.example.com/");
        });
    });
}  

这样我就会被抛出 NotImplementedException
但是,通过使用以下内容覆盖 CreateContainerExtension()

protected override IContainerExtension CreateContainerExtension() => PrismContainerExtension.Current;  

一切终于恢复正常!

如果您想使用 IServiceCollection 扩展,例如 AddHttpClient,我建议您使用 Prism 容器扩展。在您的情况下,它将是 Prism.DryIoc.Extensions。 Container Extensions 提供了很多额外的支持,包括支持通过 Service Collection extensions 注册服务。

您可以安装 Prism.Forms.Extended 并且一切正常,或者您可以按如下方式更新您的应用程序:

protected override IContainerExtension CreateContainerExtension() =>
    PrismContainerExtension.Current;

添加,因为这是我在数周的搜索中找到的唯一 post 解释如何执行此操作的方法。

我使用的是 Unity 而不是 Dryloc,但解决方案是一样的。

安装这些额外的软件包:

Prism.Forms.Extended

Prism.Unity.Extensions

protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
    //Omitted Code

    containerRegistry.RegisterServices(serviceCollection =>
    {
        serviceCollection.AddHttpClient<IApiService, ApiService>(client =>
        {
            client.BaseAddress = new Uri("Your Address Here");
        });
    });
}

public ApiService(HttpClient client)
{
    //Do Stuff
}