.net core DI中的异步提供程序

时间:2017-04-05 19:51:01

标签: c# dependency-injection async-await asp.net-core-mvc asp.net-core-webapi

我只是想知道在DI期间是否可能有async/await

执行以下操作,DI无法解析我的服务。

services.AddScoped(async provider => 
{
  var client = new MyClient();
  await client.ConnectAsync();
  return client;
});

以下内容完美无缺。

services.AddScoped(provider => 
{
  var client = new MyClient();
  client.ConnectAsync().Wait();
  return client;
});

1 个答案:

答案 0 :(得分:14)

Async / await在解析依赖关系时没有意义,因为:

这意味着所有涉及I / O的内容都应该推迟到构建对象图之后。

因此,不是注入连接的MyClient,而是MyClient第一次 时应该连接,而不是在创建它时连接。

<强>更新

由于您的MyClient不是应用程序组件,而是第三方组件,这意味着您无法确保它{s}连接[s] 首次使用&#34;。

然而,这不应该是一个问题,因为Dependency Inversion Principle已经告诉我们:

  

摘要由上层/政策层拥有

这意味着应用程序组件不应直接依赖于第三方组件,而应依赖于应用程序本身定义的抽象。作为Composition Root的一部分,可以编写实现这些抽象的适配器,并将应用程序代码调整到第三方库。

这样做的一个重要优点是,您可以控制应用程序组件使用的API,这是成功的关键,因为它允许连接问题完全隐藏在抽象背后。

以下是您的应用程序定制抽象的示例:

public interface IMyAppService
{
    Task<Data> GetData();
    Task SendData(Data data);
}

请注意,此抽象缺少ConnectAsync方法;这隐藏在抽象背后。例如,请查看以下适配器:

public class MyClientAdapter : IMyAppService
{
    private readonly Lazy<Task<MyClient>> connectedClient;

    public MyClientAdapter()
    {
        this.connectedClient = new Lazy<Task<MyClient>>(async () =>
        {
            var client = new MyClient();
            await client.ConnectAsync();
            return client;
        });
    }

    public async Task<Data> GetData()
    {
        var client = await this.connectedClient.Value;
        return await client.GetData();
    }

    public async Task SendData(Data data)
    {
        var client = await this.connectedClient.Value;
        await client.SendData(data);
    }
}

适配器从应用程序代码中隐藏有关连接的详细信息。它包含了MyClientLazy<T>的创建和连接,允许客户端只连接一次,而不管调用GetDataSendData方法的顺序如何,以及多少次。

现在,您可以让您的应用程序组件依赖于IMyAppService而不是MyClient,并将MyClientAdapter注册为具有适当生活方式的IMyAppService