使用C#将xml反序列化为超类对象

前端之家收集整理的这篇文章主要介绍了使用C#将xml反序列化为超类对象前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在创建一个程序,允许用户使用基本操作定义公式:使用 XML进行加,减,除,多.让我们举一个例子:用户想要定义像(a b)x(c d)这样的公式. xml的格式如下:

编辑我实现了这一点

编辑解决.非常感谢Yaniv的建议.我的解决方案如下:

  1. <xPlugins>
  2. <xPlugin>
  3. <Multiple>
  4. <Add>
  5. <Operator>
  6. <value>1</value>
  7. </Operator>
  8. <Operator>
  9. <value>2</value>
  10. </Operator>
  11. </Add>
  12. <Add>
  13. <Operator>
  14. <value>3</value>
  15. </Operator>
  16. <Operator>
  17. <value>4</value>
  18. </Operator>
  19. </Add>
  20. </Multiple>
  21. </xPlugin>
  22. </xPlugins>

  1. //root element
  2. public class xPlugins
  3. {
  4. [XmlElement("xPlugin",typeof(xPlugin))]
  5. public xPlugin[] Plugin { get; set; }
  6. }
  7.  
  8. public class xPlugin
  9. {
  10. [XmlElement("Multiple",typeof(Multiple))]
  11. [XmlElement("Add",typeof(Add))]
  12. [XmlElement("Subtract",typeof(Divide))]
  13. [XmlElement("Divide",typeof(Divide))]
  14. [XmlElement("Operator",typeof(Operand))]
  15. public Calculator calculator { get; set; }
  16. }
  17.  
  18. //Deseirialize ultility
  19. static class readXML
  20. {
  21. public static void getObject(ref xPlugins plugins)
  22. {
  23. try
  24. {
  25. List<Type> type = new List<Type>();
  26. type.Add(typeof(Add));
  27. type.Add(typeof(Minus));
  28. type.Add(typeof(Multiple));
  29. type.Add(typeof(Subtract));
  30. type.Add(typeof(Operator));
  31.  
  32. XmlSerializer xml = new XmlSerializer(typeof(xPlugin),type.ToArray());
  33.  
  34. FileStream fs = new FileStream("test.xml",FileMode.Open);
  35.  
  36. plugins = (xPlugins)xml.Deserialize(fs);
  37. }
  38. catch (Exception ex)
  39. {
  40. throw;
  41. }
  42. }
  43. }
  44.  
  45. public abstract class Calculator
  46. {
  47. [XmlElement("Multiple",typeof(Subtract))]
  48. [XmlElement("Divide",typeof(Operand))]
  49. public List<Calculator> calculators{ get; set; }
  50. public virtual int Calculate()
  51. {
  52. return 0;
  53. }
  54. }
  55.  
  56. public class Operator : Calculator
  57. {
  58. public int value { get; set; }
  59.  
  60. public Operator() { }
  61.  
  62. public override int Calculate()
  63. {
  64. return value;
  65. }
  66. }
  67.  
  68. public class Add : Calculator
  69. {
  70. public Add() { }
  71.  
  72. public override int Calculate()
  73. {
  74. List<int> value = new List<int>();
  75.  
  76. foreach (Calculator calculator in calculators)
  77. {
  78. value.Add(calculator.Calculate());
  79. }
  80.  
  81. return value.Sum();
  82. }
  83. }
  84.  
  85. public class Minus : Calculator
  86. {
  87. public Minus() { }
  88.  
  89. public override int Calculate()
  90. {
  91. int value = calculators[0].Calculate();
  92.  
  93. for (int i = 1; i < calculators.Count; i++)
  94. {
  95. value -= calculators[i].Calculate();
  96. }
  97.  
  98. return value;
  99. }
  100. }
  101.  
  102. public class Divide: Calculator
  103. {
  104. public Divide() { }
  105.  
  106. public override int Calculate()
  107. {
  108. int value = calculators[0].Calculate();
  109.  
  110. for (int i = 1; i < calculators.Count; i++)
  111. {
  112. value /= calculators[i].Calculate();
  113. }
  114.  
  115. return value;
  116. }
  117. }
  118.  
  119. public class Multiple : Calculator
  120. {
  121. public Multiple() { }
  122.  
  123. public override int Calculate()
  124. {
  125. int value = calculators[0].Calculate();
  126.  
  127. for (int i = 1; i < calculators.Count; i++)
  128. {
  129. value *= calculators[i].Calculate();
  130. }
  131.  
  132. return value;
  133. }
  134. }
  135.  
  136. //running test
  137. private void button1_Click(object sender,EventArgs e)
  138. {
  139. readXML.getObject(ref this.plugins);
  140.  
  141. foreach (Calculator plugin in plugins.calculators)
  142. {
  143. plugin.Calculate();
  144. }
  145. }

我只需要用以下内容装饰Calculator属性

  1. [XmlElement("Multiple",typeof(Multiple))]
  2. [XmlElement("Add",typeof(Add))]
  3. [XmlElement("Subtract",typeof(Divide))]
  4. [XmlElement("Divide",typeof(Divide))]
  5. [XmlElement("Operator",typeof(Operand))]

解决方法

我猜你想要使用XmlSerializer.
如果需要“多态”反序列化,则可以传递序列化程序应该知道的类型列表(如果它们都从相同的基类继承而不是从接口继承,则可以使用).

例:

  1. List<Type> extraTypes = new List<Type>();
  2. extraTypes.Add(typeof(multiple));
  3. extraTypes.Add(typeof(add));
  4. extraTypes.Add(typeof(substract));
  5. extraTypes.Add(typeof(divide));
  6. var ser = new XmlSerializer(typeof(Foo),extraTypes.ToArray());

它在这里解释:
Serializing and restoring an unknown class

但是还有一个问题,在你的XML中,你的操作数可以包含两种不同的类型:操作或参数(a,b,c,d),你不能在你的类中表示它.

我通常看到的是这个(我只实现了添加操作,我假设表达式是数字):

  1. public class Expression
  2. {
  3. public virtual int Evaluate()
  4. {
  5. }
  6. }
  7.  
  8. public class Add : Expression
  9. {
  10. Expression _left;
  11. Expression _right;
  12.  
  13. public Add(Expression left,Expression right)
  14. {
  15. _left = left;
  16. _right = right;
  17. }
  18.  
  19. override int Evalute()
  20. {
  21. return _left.Evalute() + _right.Evalute();
  22. }
  23. }
  24.  
  25. public class Parameter : Expression
  26. {
  27. public int Value{get;set;}
  28.  
  29. public Parameter(string name)
  30. {
  31. // Use the name however you need.
  32. }
  33.  
  34. override int Evalute()
  35. {
  36. return Value;
  37. }
  38. }

这样你只有一个基类,所以一切都更简单.如果这有意义,我想将其反序列化并不困难.

编辑:
如果基类是Calculator(而不是Expression),则XML将如下所示:

  1. <Calculator xsi:type="Multiple">
  2. <calculators>
  3. <Calculator xsi:type="Add">
  4. <calculators>
  5. <Calculator xsi:type="Operator">
  6. <value>12</value>
  7. </Calculator>
  8. </calculators>
  9. </Calculator>
  10. </calculators>
  11. </Calculator>

我创建了一个简单的计算器对象并将其序列化,这就是我所得到的.如果您将反序列化它,您将获得一个将返回12的计算器.

也许您可以使用XmlAttributes来更改XML中元素的名称,或者在最坏的情况下编写自己的反序列化器.

猜你在找的C#相关文章