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

标签 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;
});

最佳答案

虽然理论上可以在对象解析时使用async/await,但是在解析依赖时意义不大,因为:

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

所以不是注入(inject)连接的 MyClient , MyClient应该在第一次使用时连接,而不是在创建时连接。

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

但这应该不是问题,因为 Dependency Inversion Principle已经教导我们:

the abstracts are owned by the upper/policy layers

这意味着应用程序组件不应直接依赖于第三方组件,而应依赖于应用程序本身定义的抽象。作为 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> ,它允许客户端仅连接一次,与 GetData 的顺序无关和 SendData方法被调用,以及调用了多少次。

这允许您让您的应用程序组件依赖于IMyAppService而不是 MyClient并注册 MyClientAdapter作为IMyAppService拥有适当的生活方式。

关于c# - .NET Core DI 中的异步提供程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43240405/

相关文章:

c# - 异步等待 Task.FromResult(0)

c# - 如何正确使用 Task.WhenAll

c# - 如何在 PropertyValidator 重写的 IsValid 中等待方法?

c# - 使用刷新 token 的 C#sharp 身份验证的 Google.Apis 客户端

c# - 向表中插入数据时如何获取表生成的Id?

java - 设置org.springframework.scheduling.quartz.JobDetailBean的bean属性 'jobClass'

oop - 在 View 模型之间传递状态

c# - 作为 TcpClient 接收消息

c# - 数据库表中具有唯一 ID 但名称相同的不同行

ios - 使用工厂类来实例化相关具体类组