2014-10-31 28 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()) 

所以继承是要走的路..