Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Registering async factory in Autofac

I have a Wallet class that I get from a repository. I'm trying to properly register both in Autofac so classes using the wallet could have a proper instance injected. The problem is that the repository uses an async method (returning Task). Does Autofac support such cases?

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.

like image 702
Pein Avatar asked Apr 06 '13 18:04

Pein


1 Answers

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.

like image 152
svick Avatar answered Sep 18 '22 22:09

svick