2014-09-10 37 views
0

我有一個靜態類,其中我正在閱讀一個XML來構建字典。 現在這個初始化是在靜態構造函數中完成的。如何在靜態類中去除依賴項?

爲了測試這個Initialize方法,我不得不以某種方式將XML邏輯讀取出來,並給它一個XDocument進行測試,但不知道該怎麼做。

internal static class MasterMnemonicsLookup 
    { 

     private static Dictionary<string, StateCoverageMnemonic[]> masterMnemonics = new Dictionary<string, StateCoverageMnemonic[]>(); 


     private static StateCoverageMnemonic[] stateCoverageMnemonics; 



     static MasterMnemonicsLookup() 
     { 
      Initialize(); 
     } 

     private static void Initialize() 
     { 
      var resource = XDocument.Parse(GetResourceTextFile("MasterMnemonics.xml")); 
      var serializer = new XmlSerializer(typeof (MasterMnemonicsType)); 
      var model = (MasterMnemonicsType) serializer.Deserialize(resource.CreateReader()); 

      var stateCoverageMnemonicsList = new List<StateCoverageMnemonic>(); 
      foreach (var masterMnemonic in model.MasterMnemonics) 
      { 
       var stateCoverageMnemonicsXml = new List<StateCoverageMnemonic>(); 

       var excludedStates = RiskStates.None; 
       StateCoverageMnemonic allStateCoverageMnemonic = null; 
       foreach (var stateCoverageMnemonic in masterMnemonic.StateCoverageMnemonics) 
       { 
        var state = stateCoverageMnemonic.StateCode; 
        if (!state.HasFlag(RiskStates.All)) 
        { 
         excludedStates = excludedStates | state; 
         var mnemonic = stateCoverageMnemonic.Mnemonic; 
         var coverageCode = stateCoverageMnemonic.CoverageCode; 
         var stateCoverageMnemonicTemp = new StateCoverageMnemonic(state, mnemonic, coverageCode); 
         stateCoverageMnemonicsXml.Add(stateCoverageMnemonicTemp); 
        } 
        else 
        { 
         //// TODO: If All occurs twice should we throw an exception 
         allStateCoverageMnemonic = new StateCoverageMnemonic(state, stateCoverageMnemonic.Mnemonic, stateCoverageMnemonic.CoverageCode); 
        } 
       } 

       if (allStateCoverageMnemonic != null) 
       { 
        stateCoverageMnemonicsXml.Add(new StateCoverageMnemonic(RiskStates.All^excludedStates, allStateCoverageMnemonic.Mnemonic, allStateCoverageMnemonic.CoverageCode)); 
       } 

       stateCoverageMnemonicsList.AddRange(stateCoverageMnemonicsXml); 
       masterMnemonics.Add(masterMnemonic.MasterMnemonic, stateCoverageMnemonicsXml.ToArray()); 
      } 

      stateCoverageMnemonics = stateCoverageMnemonicsList.ToArray(); 
     } 

     private static string GetResourceTextFile(string filename) 
     { 
      string result = string.Empty; 

      using (Stream stream = typeof(MasterMnemonicsLookup).Assembly.GetManifestResourceStream("Geico.Applications.Business.CoverageApi.DomainLayer.DataLayer." + filename)) 
      { 
       var streamReader = new StreamReader(stream); 
       result = streamReader.ReadToEnd(); 
      } 
      return result; 
     } 
    } 

回答

2

不建議以這種方式使用靜態構造函數,而您的場景就是一個很好的例子。您可以使用接受XDocument的公共實例構造函數來嘗試單例模式。 (你可以使用內部的,但這使得單元測試更難)。這是一種簡單的依賴注入形式。

爲了測試,您的類的實例可以簡單地由您的測試框架和測試XDocument創建。

對於您的實時應用程序,您的類的靜態實例可以通過容器類型進行初始化和保存,並且適當的XDocument可以私下傳遞(在容器內)。

+0

我同意,這是更好地使MasterMnemonicsLookup到一個非靜態類和加載時的內容應用程序啓動或延遲並保持對容器中實例化的MasterMnemonicsLookup實例的引用。除了可能引發的異常之外,XmlSerializer首次執行序列化可能非常耗時,因爲它會在內部生成一個程序集來執行序列化。如果在此期間還有其他線程正在加載類型,則它們的靜態構造函數將被暫時阻止。 – 2014-09-10 10:59:38

+0

我不明白如果我添加一個實例構造函數,該類是如何單身? – Charu 2014-09-10 11:15:25

+1

類型本身不會是單例,但如果容器類型負責創建它的唯一實例,則可以將其視爲單例。我假設這不是你正在創建的公共圖書館,所以它將是公共的,而不是靜態的應該不重要。這是Google推薦的模式:例如,請參閱http://googletesting.blogspot.com/2008/08/where-have-all-singletons-gone.html。 – DvS 2014-09-10 11:30:00

0

我同意Darious沃恩 - 斯科特

但是如果你想使用靜態構造函數,讓你可以把它放到加載邏輯放到一個單獨的類,這使得它更容易測試。

例如

 internal class MasterMnemonicsLoader 
     { 
     public void Load(
      XDocument resource, 
      Dictionary<string, StateCoverageMnemonic[]> masterMnemonics, 
      StateCoverageMnemonic[] stateCoverageMnemonics) 
     { 
      //Do the loading here 

     } 
    } 

,並在初始化方法,你可以調用Load方法

private static void Initialize() 
{ 
    var resource = XDocument.Parse(GetResourceTextFile("MasterMnemonics.xml")); 
    var loader = MasterMnemonicsLoader(); 
    loader.Load(resource, masterMnemonics, stateCoverageMnemonics);