wai*_*rit 11 c# dependency-injection async-await asp.net-core-mvc asp.net-core-webapi
我只是想知道async/await在DI期间是否有可能.
执行以下操作,DI无法解析我的服务.
services.AddScoped(async provider =>
{
var client = new MyClient();
await client.ConnectAsync();
return client;
});
Run Code Online (Sandbox Code Playgroud)
以下作品完美无缺.
services.AddScoped(provider =>
{
var client = new MyClient();
client.ConnectAsync().Wait();
return client;
});
Run Code Online (Sandbox Code Playgroud)
Ste*_*ven 17
解析依赖项时,Async/await没有意义,因为:
这意味着所有涉及I/O的内容都应该推迟到构建对象图之后.
因此,不是注入连接MyClient,而是MyClient应该在第一次使用时连接,而不是在创建时连接.
UPDATE
由于您MyClient不是应用程序组件而是第三方组件,这意味着您无法确保它" 首次使用时连接[s] ".
然而,这应该不是问题,因为依赖性倒置原则已经教会我们:
摘要由上层/政策层拥有
这意味着应用程序组件不应直接依赖于第三方组件,而应依赖于应用程序本身定义的抽象.作为组合根的一部分,可以编写实现这些抽象的适配器并使应用程序代码适应第三方库.
这样做的一个重要优点是,您可以控制应用程序组件使用的API,这是成功的关键,因为它允许连接问题完全隐藏在抽象背后.
以下是您的应用程序定制抽象可能如下所示的示例:
public interface IMyAppService
{
Task<Data> GetData();
Task SendData(Data data);
}
Run Code Online (Sandbox Code Playgroud)
请注意,这种抽象缺乏一种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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
适配器从应用程序代码中隐藏有关连接的详细信息.它包装的创建和连接MyClient的Lazy<T>,它允许客户将只需一次连接,独立于何种顺序GetData和SendData方法被调用,多少次.
现在你可以让你的应用程序组件的依赖IMyAppService,而不是MyClient和注册MyClientAdapter为IMyAppService具有适当的生活方式.