2013-04-06 111 views
2

我有一個從存儲庫中獲取的Wallet類。我試圖在Autofac中正確註冊,所以使用錢包的類可以注入適當的實例。問題是存儲庫使用異步方法(返回任務)。 Autofac是否支持這種情況?在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>()我得到一個異常說錢包未註冊。

+0

您是否可以包含使用代碼或至少使用注入依賴關係的ctor和example方法? – 2013-04-06 20:14:56

+0

沒有回答這個問題,但我想說你的WalletRepository不應該需要IO初始化。嘗試初次使用其中一種方法時首先使用它。 – usr 2013-04-06 20:31:51

+0

它不是使用IO初始化的存儲庫,而是一個Wallet對象(它們是從文件加載的)。 – Pein 2013-04-06 21:34:47

回答

6

除非我誤認爲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具有一定的擴展點,使這個代碼更簡單,但我不知道有足夠的瞭解它來幫你。

1

一個選項是讓註冊做到將異步調用轉換爲結果所需的阻塞。

即:

這意味着AutoFac將被迫做阻塞時的依賴性都解決了,服務的客戶端不需要知道服務工廠異步。

這是否是一個好主意,在很大程度上取決於你在做什麼。

0

這可能會導致死鎖。 Autofac在處理不同生命週期範圍的解析的一些邏輯中使用鎖。所以如果異步工廠操作將嘗試解決另一個線程中的某些問題,您將會遇到死鎖