简体   繁体   English

在Autofac中注册异步工厂

[英]Registering async factory in Autofac

I have a Wallet class that I get from a repository. 我有一个从存储库中获取的Wallet类。 I'm trying to properly register both in Autofac so classes using the wallet could have a proper instance injected. 我正在尝试在Autofac中正确注册,因此使用钱包的类可以注入适当的实例。 The problem is that the repository uses an async method (returning Task). 问题是存储库使用异步方法(返回Task)。 Does Autofac support such cases? Autofac是否支持此类案例?

This doesn't work: 这不起作用:

cb.RegisterType<WalletRepository>()
    .As<IWalletRepository>()
    .SingleInstance();
cb.Register(async c => await c.Resolve<IWalletRepository>().CreateAsync(App.WalletPath));
cb.RegisterType<ViewModel>()
    .AsSelf().
    .SingleInstance();

Somewhere in the app I just have: 在应用程序的某个地方我只有:

class ViewModel
{
    public ViewModel(Wallet wallet)
    {
        //nothing fancy here
    }
}

When calling container.Resolve<ViewModel>() i get an exception saying Wallet is not registered. 当调用container.Resolve<ViewModel>()我得到一个例外,说Wallet没有注册。

Unless I'm mistaken Autofac doesn't have any specific support for async factories. 除非我弄错了Autofac对async工厂没有任何特定的支持。 You can still make it work, but you have to write some boilerplate code, because constructor injection won't work. 您仍然可以使它工作,但您必须编写一些样板代码,因为构造函数注入将不起作用。 You also have to be more literal and say you want Task<T> instead of T . 你还必须更加文字,并说你想要Task<T>而不是T The whole code would look something like this: 整个代码看起来像这样:

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>>();

It's possible Autofac has some extensibility points to make this code simpler, but I don't know enough about it to help you with that. Autofac可能有一些扩展点可以使这个代码更简单,但我不太了解它可以帮助你。

One option is just to make the registration do the blocking required to convert the async call into it's result. 一种选择只是使注册执行将异步调用转换为结果所需的阻塞。

ie: 即:

cb.Register(c => c.Resolve<IWalletRepository>().CreateAsync(App.WalletPath).Result); // nb: blocking call

This means that AutoFac will be forced to do the blocking when the dependencies are resolved, and the client of the service need not know that the service factory was async. 这意味着在解析依赖关系时,AutoFac将被强制执行阻止,并且服务的客户端不需要知道服务工厂是异步的。

Whether this is a good idea will depend largely on what you are doing at the time of course. 这是否是一个好主意在很大程度上取决于你当然正在做什么。

This might cause a deadlock. 这可能会导致死锁。 Autofac is using locks in some of the logic that handles the resolving for different lifetime scopes. Autofac在一些处理不同生命周期范围的解析的逻辑中使用锁。 so if the the async factory operation will try to resolve something in another thread you will get a deadlock 因此,如果异步工厂操作将尝试解析另一个线程中的某些内容,则会出现死锁

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM