Registering async factory in Autofac

99封情书 提交于 2019-12-05 10:53:41

Unless I'm mistaken Autofac doesn't have any specific support for async factories. 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. 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.

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.

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. so if the the async factory operation will try to resolve something in another thread you will get a deadlock

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!