[英]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 的事情都應該推遲到構建對象圖之后。
因此,與其注入連接的MyClient
, MyClient
應該在第一次使用時進行連接,而不是在創建時進行連接。
由於您的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>
,這允許客戶端只連接一次,與調用GetData
和SendData
方法的順序以及調用次數無關。
這可以讓你讓你的應用程序組件取決於IMyAppService
而不是MyClient
並注冊MyClientAdapter
作為IMyAppService
與適當的生活方式。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.