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

5
我有一个使用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之前,就是这样。

现在,要添加它,我们应该在IServiceCollection上使用AddHttpClient()。这就是我认为需要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调用失败了。

在使用DryIoc和Prism for Xamarin.Forms时,使用IServiceProvider的正确模式是什么?不幸的是,在这方面没有文档或开源代码可用,我有点迷失。

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

更新#1

根据 Dan S. 的建议,已卸载 DryIoc.Microsoft.DependencyInjection,使项目回到尝试使用 IServiceCollection 依赖项(在我的情况下是 IHttpClientFactory)之前的状态,然后我安装了 Prism.Forms.ExtendedPrism.DryIoc.Extensions
此后,在 App.xaml.cs 中的 CreateContainerExtension() 变为:
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;
}

现在从RegisterTypes()中删除了containerRegistry.Register<IExampleService, ExampleService>();

现在ExampleService终于得到了它的HttpClient注入,一切正常工作。

更新#2

Prism相关的唯一包是Prism.DryIoc.FormsPrism.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;  

一切终于恢复正常了!

2个回答

7
如果您想使用AddHttpClient等IServiceCollection扩展功能,建议您使用Prism容器扩展。 在您的情况下,可以使用Prism.DryIoc.Extensions。 容器扩展提供了很多额外的支持,包括通过Service Collection扩展注册服务的支持。
您可以安装Prism.Forms.Extended,这样所有的工作都会自动完成,或者按照以下方式更新您的应用程序:
protected override IContainerExtension CreateContainerExtension() =>
    PrismContainerExtension.Current;

2
非常明确地说,您将不会使用已被弃用的 Prism.DryIoc.Forms.Extended。您需要安装 Prism.Forms.Extended 以及所需容器的扩展包。它将自动连接,您不需要做任何与普通 Prism 应用程序不同的事情。 - Dan Siegel
1
@YanKarin,接近了,但是要去掉CreateContainerExtension...你的注册应该在RegisterTypes方法中与其他任何注册一起使用ContainerRegistry进行。 - Dan Siegel
1
你不应该在Prism.DryIoc.Extensions中使用Prism.DryIoc.Forms。要么保持代码与Prism.Forms一致,要么停止尝试覆盖CreateContainerExtension并使用Prism.Forms.Extended与Prism.DryIoc.Extensions。 - Dan Siegel
1
如果我尝试使用Prism.Forms和Prism.DryIoc.Extensions,那么无法定位PrismApplication,因为它未包含在Prism.Forms软件包中。你确定我不应该使用Prism.DryIoc.Forms吗?我认为这是唯一的方法,如果不想使用Prism.Forms.Extended,就可以拥有PrismApplication。 - Oliver
2
如果您使用的是Prism.Forms而不是Prism.Forms.Extended,那么您需要从PrismApplicationBase继承。CreateContainerExtension是PrismApplication在容器特定包中实现的唯一内容。由于您正在使用Prism.DryIoc.Extensions,因此不应该引用Prism.DryIoc.Forms。希望这能为您澄清问题。 - Dan Siegel
显示剩余3条评论

0

因为这是我数周搜索中唯一解释如何完成此操作的帖子,所以补充一下。

我正在使用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
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接