2017-03-07 34 views
1

首先,讓我說我已經閱讀了幾個關於SingleInstance的問題,但仍然找不到幫助我的直接答案。也就是說,如果我錯過了任何事情,我很抱歉。Autofac SingleInstance()和Xamarin表單

我的問題是:

我建立一個Xamarin窗體應用程序適用於iOS和Android。我在PCL中有一個AppInitializer類,我使用Autofac註冊了我的所有接口依賴項。然後,我將構建器中的Container作爲應用程序類的靜態屬性。我遇到的問題是,雖然我使用.SingleInstance()註冊了所有內容,但實際上我並沒有獲得單個實例。

初始化邏輯實例:

var builder = new ContainerBuilder(); 
builder.RegisterType<ErrorHandler>().SingleInstance().As<IErrorHandler>(); 
… 
builder.RegisterType<MemberViewModel>().SingleInstance().As<IMemberViewModel>(); 
… 
AppContainer.Current = builder.Build(); 

我又讓Autofac處理在我的構造函數解析接口。例如:

public MemberViewModel(ISettingsViewModel settings, IErrorHandler errorHandler, …) : base(settings, errorHandler){…} 

我然後說使用模型中的頁面,如下的:

示例頁用法:

public ProfilePage() 
{ 
    InitializeComponent(); 
    var displayModel = Model.CurrentMember; 
    … 
} 
… 
**public IMemberViewModel Model => 
AppContainer.Current.Resolve<IMemberViewModel>();** 

在這個例子中,我到達之前,立即設置Model.CurrentMember的屬性在本頁。我已經設置了斷點,並知道這是發生的事實。但是,當我解析模型的實例時,CurrentMember上的屬性爲空。

我在這裏做錯了什麼,或者我遇到過錯誤?

-Edit- 明確表示我正在使用Autofac。

-Edit 2- 添加更多細節。

我對IMemberViewModel類的實現有不同的屬性,包括一個名爲當前成員的可觀察對象。它的聲明如下:

public class MemberViewModel : ViewModelBase, IMemberViewModel 
{ 
    … 
    (see constructor above) 
    … 
    public MemberDisplay CurrentMember => 
     m_CurrentMember ?? (m_CurrentMember = new MemberDisplay()) 

在IMemberViewModel執行我有集上CurrentMember的各種屬性的方法。

操作的順序是這樣的:

最終用戶敲擊一個圖像獲得部件。這會在IMemberViewModel實現的(理論上)單例實例上觸發命令。此命令執行一個異步任務,等待API的異步調用以加載該成員的數據。在加載數據並在CurrentMember上設置屬性後,該應用將導航到配置文件屏幕。配置文件屏幕可以解析IMemberViewModel(每個以上)。

預期的行爲: 從IMemberViewModel的解決實例的上CurrentMember屬性被設置爲剛纔已經從負載數據的方法設置的值。這種期望來自於假設有一個IMemberViewModel實例。

實際行爲: 的CurrentMember的屬性的默認值,即的String.Empty,0,空,等

這裏奇怪的是,這不會發生在每一個模型。我有一個消息模型,我在同一個屏幕上以同樣的方式解決,似乎很好。

+1

當你說你在到達頁面之前設置了'Model.CurrentMember'的屬性,你的意思是你從同一個容器中解析了'IMemberViewModel'並設置了屬性? –

+0

模型上的CurrentMember是一個具有幾個字符串屬性的可觀察對象。我在IMemberViewModel的實現中直接從加載數據調用中設置這些字符串(例如名稱)。我的期望是,當我解決IMemberViewModel時,我得到了實現的單個實例。相反,我正在獲得該實現的新實例。我會更詳細地更新我的問題。 – Kerfuffle

+0

@MickaëlDerriey。我忘了在我的回覆中標記你。 – Kerfuffle

回答

0

這個問題原來是由我們開始初始化所有事情的方式引起的。爲了後代的緣故,我將簡要分析發生了什麼,以及我做了什麼來阻止它。

上應用流量:

  • 應用打開&構造函數被調用。這將調用上面的初始化例程。
  • 用戶登錄
  • 使用靜態容器解析IMemberViewModel的第一個實例。
  • 彈出消息詢問推送通知權限
  • 用戶發生這種情況時,該應用OnSleep被稱爲(IOS)
  • 用戶選擇一個回答後,的onResume被調用。
  • OnResume調用初始化例程
  • 新建容器已創建。
  • 調用加載數據發生在舊容器上,新頁面引用新容器。
  • 問題如上所述出現。

更正流程:

首先,我可以告訴初始化調用不需要在簡歷製作和/或如果應用程序的構造做出啓動。如果應用程序因爲其他應用程序需要內存空間而「被殺害」,則將在下次啓動時創建新版本的應用程序(請參閱Android Activity LifecycleiOS App Lifecycle)。其次,因爲我是偏執狂,因爲它不會傷害,所以在應用程序初始化例程中,我現在檢查以確定容器是否存在以及接口是否已經註冊。

public static void Init(ISetup setup) 
{ 
    if (Container != null && IsModelRegistered()) return; 

    RegisterDependencies(setup); 
    … 
} 

private static bool IsModelRegistered() 
{ 
    return Container.IsRegistered<IMemberViewModel>(); 
}