2014-10-31 30 views
3

我有一個應用程序,其中有許多從XML文件派生的類(該類中的屬性名稱與XML中的節點名稱相匹配),我可以使用反射來填充這個類(我在我改編的stackoverflow上找到的一些代碼)。本質上,我枚舉XML節點的所有子節點,並嘗試在我的類中獲取和設置相應的屬性名稱。這工作得很好。雖然我明白XML序列化可能是一個更好的解決方案,但我確定我已經擁有了。我的問題是我如何處理人口稠密的課程。幫助我創建C#中的泛型類字典的方法

讀取XML,我會(比方說)得到200個節點,可以轉換爲給定類的200個實例。我想將這些存儲在字典中。然後我會有另一個XML(比如說)生成一個不同類的100個實例,並且我希望這些實例存儲在不同的字典中。

我用它來解析XML代碼如下:

Dictionary<string, Book> oBookCollection = new Dictionary<string, Book>(); 
XML_File_Reader oDoc = new XML_File_Reader(@"C:\apps\bookList.xml"); 
if (oDoc.IsDocumentValid) 
{ 
    XmlNodeList oList = oDoc.GetList("Row"); 
    if (oList.Count !=0) 
    foreach (XmlNode xn in oList) 
    { 

     XmlNode oThisNode = xn; 
     Book oThisBook = new Book(oMyLibrary, oThisNode); 

     oDoc.MigrateXMLtoObject(oBuilding, oThisNode); 
     oBookCollection .Add(oBook.BookName, oBook); 

    } 

} 
oDoc = null; 

正如你所看到的,這有一個特定的類類型的具體引用。我希望能夠使用一種通用的方法,就像書籍一樣可以輕鬆填充DVD和玩具的XML。

對於信息,現有的「MigrateXMLtoObject」程序如下:

public void MigrateXMLtoObject(object myObject, XmlNode node) 
    { 
     if (node == null) 
     { 
      return; 
     } 

     PropertyInfo propertyInfo; 
     IEnumerator list = node.GetEnumerator(); 
     XmlNode tempNode; 

     while (list.MoveNext()) 
     { 
      tempNode = (XmlNode)list.Current; 

      propertyInfo = myObject.GetType().GetProperty(tempNode.Name); 


      if (propertyInfo != null) 
      { 
       if (propertyInfo.PropertyType == typeof(DateTime)) 
       { 
        DateTime val = DateTime.MinValue; 
        DateTime.TryParse(tempNode.InnerText, out val); 
        propertyInfo.SetValue(myObject, val, null); 
       } 
       else if (propertyInfo.PropertyType == typeof(Int32)) 
       { 
        int val = 0; 
        Int32.TryParse(tempNode.InnerText, out val); 
        propertyInfo.SetValue(myObject, val, null); 
       } 
       else if (propertyInfo.PropertyType == typeof(bool)) 
       { 
        bool val = false; 
        Boolean.TryParse(tempNode.InnerText, out val); 
        propertyInfo.SetValue(myObject, val, null); 
       } 
       else if (propertyInfo.PropertyType == typeof(string)) 
       { 
        string val = ""; 
        val = tempNode.InnerText; 
        propertyInfo.SetValue(myObject, val, null); 
       } 
       else 
       { 
        propertyInfo.SetValue(myObject, tempNode.Value, null); 
       } 
      } 

     } 
    } 

我認爲正在本本的東西,DVD光盤等公共基類繼承,但不認爲將工作,因爲如果我將BaseClass傳遞給方法,當它嘗試使用反射來匹配屬性時,它們將是基類的屬性而不是派生類。

然後我在這裏做了一些搜索,看到提及使用泛型。不幸的是,雖然我使用字典<>和列表<>對象,但我從來沒有寫過自己的Generic,所以不知道如何使用它們(也不知道這實際上是我正在尋找的解決方案!)

我寫這篇文章,並明確將無法正常工作/不會編譯,但它可能是一種有用的片段讓人們把我推在正確的方向:

public Dictionary<string, T> MigrateXMLtoObject<T>(string xmlPath, MyLibrary oLibrary) 
    { 
     Dictionary<string, T> oDictionary = new Dictionary<string, T>(); 

     XML_File_Reader oDoc = new XML_File_Reader(xmlPath); 
     if (oDoc.IsDocumentValid) 
     { 
      XmlNodeList oList = oDoc.GetList("Row"); 
      if (oList.Count != 0) 
       foreach (XmlNode xn in oList) 
       { 

        XmlNode oThisNode = xn; 
        //T othisItem = new T(oLibrary, oThisNode); 

        oDoc.MigrateXMLtoObject(T, oThisNode); 
        oDictionary.Add(T.Type, T); 

       } 

     } 
     oDoc = null; 

     return oDictionary; 
    } 

我需要某種形式的'開關'來評估T,並創建相應的基類?

謝謝!

回答

1

沒有更多的上下文,很難確切知道什麼最適合你。但天真的,這裏是我建議:

public Dictionary<string, T> MigrateXMLtoObject<T>(
    string xmlPath, MyLibrary oLibrary, Func<MyLibrary, XmlNode, T> factory) 
{ 
    Dictionary<string, T> oDictionary = new Dictionary<string, T>(); 

    XML_File_Reader oDoc = new XML_File_Reader(xmlPath); 
    if (oDoc.IsDocumentValid) 
    { 
     XmlNodeList oList = oDoc.GetList("Row"); 
     if (oList.Count != 0) 
      foreach (XmlNode xn in oList) 
      { 

       XmlNode oThisNode = xn; 
       T thisItem = factory(oLibrary, oThisNode); 

       // It's not really clear to me what you wanted to do 
       // here. If the object constructor is handling applying 
       // the node data to the object, you shouldn't need to 
       // "migrate" more, right? And the dictionary seems to 
       // want to add the object as the value, with the key 
       // being some text. Where do you get the key? 
       //oDoc.MigrateXMLtoObject(T, oThisNode); 
       oDictionary.Add(objectKey, thisItem); 

      } 

    } 
    oDoc = null; 

    return oDictionary; 
} 

在哪裏你怎麼稱呼它是這樣的:

MigrateXMLtoObject(xmlPath, library, (l, n) => new Book(l, n)); 

需要注意的是,如果你只傳遞MyLibrary對象傳遞給構造函數的目的的對象,那麼在這種方法中,您不需要將其作爲方法參數。相反,您可以將其構建到工廠代表中。例如: -

MigrateXMLtoObject(xmlPath, node => new Book(library, n)); 

我也建議你擺脫所有的「O」的前綴的變量名。這沒有幫助。:)

+0

感謝你。我有這樣的發揮,看看(我之前沒有使用Function Delegates,所以這是一個很好的學習體驗!)Key實際上是一個(幸運的)獨特的節點元素,在Book&DVD類中,它被稱爲「Type」這是一個愚蠢的名字....我將從XML節點中獲取它,而不是嘗試從新創建的類中獲取它。在遷移問題上,對象構造函數只是通過MyLibrary,作爲父母有效。 – ainwood 2014-10-31 19:41:55

0

我認爲都使得書籍,DVD等從 一個公共基類繼承,但不認爲會的工作,因爲如果我通過 的BaseClass的該方法的東西的時候,它嘗試使用反射來匹配 的屬性,它們將是基類的屬性而不是 派生類。

抱歉,但是,你想錯了:(..

public void SayMyType(BaseClass obj) 
{ 
     Console.Write(obj.GetType())//will output the type of object 'DerivedClass' not the parameter 'BaseClass ' 
} 
SayMyType(new DerivedClass()) 

所以繼承是要走的路..