在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中注册异步工厂

除非我弄错了,否则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将被迫在解决依赖关系时执行阻塞,并且服务的客户端不需要知道服务工厂是异步的。

当然,这是否是个好主意在很大程度上取决于你当时正在做什么。