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

前端之家收集整理的这篇文章主要介绍了c# – .net core DI中的异步提供程序前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我只是想知道在DI期间是否可以进行异步/等待.

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

  1. services.AddScoped(async provider =>
  2. {
  3. var client = new MyClient();
  4. await client.ConnectAsync();
  5. return client;
  6. });

以下作品完美无缺.

  1. services.AddScoped(provider =>
  2. {
  3. var client = new MyClient();
  4. client.ConnectAsync().Wait();
  5. return client;
  6. });

解决方法

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

> Constructors can’t be asynchronous,和
>对象图的构造应为simple,reliable and fast

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

因此,MyClient不是注入连接的MyClient,而是在第一次使用时连接,而不是在创建时连接.

UPDATE

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

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

the abstracts are owned by the upper/policy layers

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

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

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

  1. public interface IMyAppService
  2. {
  3. Task<Data> GetData();
  4. Task SendData(Data data);
  5. }

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

  1. public class MyClientAdapter : IMyAppService
  2. {
  3. private readonly Lazy<Task<MyClient>> connectedClient;
  4.  
  5. public MyClientAdapter()
  6. {
  7. this.connectedClient = new Lazy<Task<MyClient>>(async () =>
  8. {
  9. var client = new MyClient();
  10. await client.ConnectAsync();
  11. return client;
  12. });
  13. }
  14.  
  15. public async Task<Data> GetData()
  16. {
  17. var client = await this.connectedClient.Value;
  18. return await client.GetData();
  19. }
  20.  
  21. public async Task SendData(Data data)
  22. {
  23. var client = await this.connectedClient.Value;
  24. await client.SendData(data);
  25. }
  26. }

适配器从应用程序代码中隐藏有关连接的详细信息.它将MyClient的创建和连接包装在Lazy< T>中,它允许客户端只连接一次,而不管调用GetData和SendData方法的顺序,以及多少次.

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

猜你在找的.NET Core相关文章