在Autofac中注册异步工厂
本文关键字:异步 工厂 注册 Autofac | 更新日期: 2023-09-27 18:07:54
我有一个从存储库获得的Wallet类。我正试图在autofacc中正确注册,以便使用钱包的类可以注入适当的实例。问题是存储库使用异步方法(返回Task)。Autofac支持这种情况吗?
这不起作用:
cb.RegisterType<WalletRepository>()
.As<IWalletRepository>()
.SingleInstance();
cb.Register(async c => await c.Resolve<IWalletRepository>().CreateAsync(App.WalletPath));
cb.RegisterType<ViewModel>()
.AsSelf().
.SingleInstance();
在应用程序的某个地方,我只有:
class ViewModel
{
public ViewModel(Wallet wallet)
{
//nothing fancy here
}
}
当调用container.Resolve<ViewModel>()
时,我得到一个异常,说钱包没有注册。
除非我弄错了,否则Autofac对async
工厂没有任何特定的支持。您仍然可以使它工作,但是必须编写一些样板代码,因为构造函数注入不起作用。你也必须更字面地说你想要Task<T>
而不是T
。整个代码看起来像这样:
cb.RegisterType<WalletRepository>()
.As<IWalletRepository>()
.SingleInstance();
cb.Register(c => c.Resolve<IWalletRepository>().CreateAsync(App.WalletPath));
cb.Register(async c => new ViewModel(await c.Resolve<Task<Wallet>>()))
.SingleInstance();
var container = cb.Build();
var viewModel = await container.Resolve<Task<ViewModel>>();
Autofac可能有一些扩展点使这段代码更简单,但我对它的了解不够,无法帮助您。
这可能导致死锁。Autofac在处理不同生命周期范围的解析的一些逻辑中使用了锁。因此,如果异步工厂操作试图在另一个线程中解决某些问题你会得到死锁
一种选择是让注册完成将异步调用转换为结果所需的阻塞。
ie:cb.Register(c => c.Resolve<IWalletRepository>().CreateAsync(App.WalletPath).Result); // nb: blocking call
这意味着AutoFac将被迫在解决依赖关系时执行阻塞,并且服务的客户端不需要知道服务工厂是异步的。
当然,这是否是个好主意在很大程度上取决于你当时正在做什么。