繁体   English   中英

.NET Core DI 中的异步提供程序

[英]Async provider in .NET Core DI

我只是想知道在 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;
});

虽然理论上可以在对象解析过程中使用 async/await,但在解析依赖关系时并没有多大意义,因为:

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

因此,与其注入连接的MyClientMyClient应该在第一次使用时进行连接,而不是在创建时进行连接。

由于您的MyClient不是应用程序组件而是第三方组件,这意味着您无法确保它“在第一次使用时连接[s]”。

然而,这应该不是问题,因为依赖倒置原则已经告诉我们:

摘要归上层/策略层所有

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

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

下面是一个示例,说明您的应用程序定制的抽象可能是什么样子:

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

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

public sealed class MyClientAdapter : IMyAppService, IDisposable
{
    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);
    }

    public void Dispose()
    {
        if (this.connectedClient.IsValueCreated)
        {
            this.connectedClient.Value.Dispose();
        }
    }
}

适配器对应用程序代码隐藏了连接细节。 它将MyClient的创建和连接包装在一个Lazy<T> ,这允许客户端只连接一次,与调用GetDataSendData方法的顺序以及调用次数无关。

这可以让你让你的应用程序组件取决于IMyAppService而不是MyClient并注册MyClientAdapter作为IMyAppService与适当的生活方式。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM