2014-01-28 81 views
1

我剛剛完成我的新應用程序,但卡住了。我的應用程序分爲兩部分 - 遠程和本地。我需要的是基於某些異步反序列化的應用程序設置爲接口註冊一個類。這裏是'想法代碼'靜態構造函數之前的異步加載設置

public class ViewModelLocator 
{ 
    static ViewModelLocator() 
    { 
     ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default); 

     // It can't work :(((
     if(await SettingsManager.LoadSettings().EnableRemote) // <<<<<< 
     { 
      SimpleIoc.Default.Register<IMyService, MyRemoteService>(); 
     } 
     else 
     { 
      SimpleIoc.Default.Register<IMyService, MyLocalService>(); 
     } 

     SimpleIoc.Default.Register<MainViewModel>(); 
     SimpleIoc.Default.Register<SomeOtherViewModel>(); 
    } 

我怎麼能解決它?這些設置在我的WinRT應用程序的獨立存儲中的XML文件中被序列化。請,你能想出任何建議嗎?

+0

不要使用異步用於加載配置?無論如何知道設置何時加載?如果有,然後手動加載並等待完成。 – TyCobb

回答

3

它有點破壞了IoC模式以異步註冊綁定。您需要將異步設置合併到包裝類中。這個包裝類應負責:

  1. 加載設置
  2. 提供實際執行IMyService

如果IMyService有同步的方法,那麼你可能必須改變它,要麼提供所有方法的異步版本,或者提供屬性+事件,以便消費者知道何時訪問是安全的。但如果它是一種服務,它的方法可能已經是異步的了,對嗎?

作爲一個例子,我們稱之爲包裝類MyServiceWrapper。它將在第一次構建時加載設置,並通過IMyService中的所有異步方法(例如,如下所示的SomeMethodAsync)。

public interface IMyService 
{ 
    Task SomeMethodAsync(Action<bool> callback); 
} 

public class MyServiceWrapper : IMyService 
{ 
    private IMyService _impl = null; 
    private IMyService _remote, _local; 
    private bool _loaded = false; 
    private object _sync = new object(); 

    public Task SomeMethodAsync(Action<bool> callback) 
    { 
     // first make sure the settings have been loaded 
     await LoadSettings(); 
     _impl.SomeMethodAsync(callback); 
    } 

    public MyServiceWrapper(MyRemoteService remoteService, MyLocalService localService) 
    { 
     _remote = remoteService; 
     _local = localService; 
     LoadSettings(); 
    } 

    private async Task<bool> LoadSettings() 
    { 
     if (_loaded) 
      return true; 
     // lock to prevent multiple threads from loading the settings 
     lock (_sync) 
     { 
      if (_loaded) 
       return true; 

      if(await SettingsManager.LoadSettings().EnableRemote) 
       _impl = _remote; 
      else 
       _impl = _local; 
     } 
     return true; 
    } 
} 

現在你可以有你的DI容器寄存器:

  • MyRemoteService - >MyRemoteService
  • MyLocalService - >MyLocalService
  • IMyService - >MyServiceWrapper
+1

您可能想要在'LoadSettings'內添加'try/catch',並通過'SettingsLoaded'事件傳播任何錯誤。否則,如果LoadSettings中有任何內容拋出,則無法在'LoadSettings'之外處理它。 – Noseratio

+0

謝謝@Noseratio,這兩點都不錯。我修復了'任務'。 – McGarnagle

+0

NP,但它仍然有點令人困惑,LoadSettings()。EnableRemote'上的'EnableRemote'是什麼?你的意思是如果(等待SettingsManager.LoadSettings())'? – Noseratio