我正在创建一个程序,允许用户使用 4 种基本操作定义公式:使用 XML 进行加、减、除、乘。让我们举个例子:用户想要定义像 (a + b) x (c + d)
这样的公式。 xml格式如下:
编辑我已经实现了这个
编辑 解决。非常感谢 Yaniv 的建议。我的解决方案如下:
<xPlugins>
<xPlugin>
<Multiple>
<Add>
<Operator>
<value>1</value>
</Operator>
<Operator>
<value>2</value>
</Operator>
</Add>
<Add>
<Operator>
<value>3</value>
</Operator>
<Operator>
<value>4</value>
</Operator>
</Add>
</Multiple>
</xPlugin>
</xPlugins>
类
//root element
public class xPlugins
{
[XmlElement("xPlugin", typeof(xPlugin))]
public xPlugin[] Plugin { get; set; }
}
public class xPlugin
{
[XmlElement("Multiple", typeof(Multiple))]
[XmlElement("Add", typeof(Add))]
[XmlElement("Subtract", typeof(Divide))]
[XmlElement("Divide", typeof(Divide))]
[XmlElement("Operator", typeof(Operand))]
public Calculator calculator { get; set; }
}
//Deseirialize ultility
static class readXML
{
public static void getObject(ref xPlugins plugins)
{
try
{
List<Type> type = new List<Type>();
type.Add(typeof(Add));
type.Add(typeof(Minus));
type.Add(typeof(Multiple));
type.Add(typeof(Subtract));
type.Add(typeof(Operator));
XmlSerializer xml = new XmlSerializer(typeof(xPlugin), type.ToArray());
FileStream fs = new FileStream("test.xml", FileMode.Open);
plugins = (xPlugins)xml.Deserialize(fs);
}
catch (Exception ex)
{
throw;
}
}
}
public abstract class Calculator
{
[XmlElement("Multiple", typeof(Multiple))]
[XmlElement("Add", typeof(Add))]
[XmlElement("Subtract", typeof(Subtract))]
[XmlElement("Divide", typeof(Divide))]
[XmlElement("Operator", typeof(Operand))]
public List<Calculator> calculators{ get; set; }
public virtual int Calculate()
{
return 0;
}
}
public class Operator : Calculator
{
public int value { get; set; }
public Operator() { }
public override int Calculate()
{
return value;
}
}
public class Add : Calculator
{
public Add() { }
public override int Calculate()
{
List<int> value = new List<int>();
foreach (Calculator calculator in calculators)
{
value.Add(calculator.Calculate());
}
return value.Sum();
}
}
public class Minus : Calculator
{
public Minus() { }
public override int Calculate()
{
int value = calculators[0].Calculate();
for (int i = 1; i < calculators.Count; i++)
{
value -= calculators[i].Calculate();
}
return value;
}
}
public class Divide: Calculator
{
public Divide() { }
public override int Calculate()
{
int value = calculators[0].Calculate();
for (int i = 1; i < calculators.Count; i++)
{
value /= calculators[i].Calculate();
}
return value;
}
}
public class Multiple : Calculator
{
public Multiple() { }
public override int Calculate()
{
int value = calculators[0].Calculate();
for (int i = 1; i < calculators.Count; i++)
{
value *= calculators[i].Calculate();
}
return value;
}
}
//running test
private void button1_Click(object sender, EventArgs e)
{
readXML.getObject(ref this.plugins);
foreach (Calculator plugin in plugins.calculators)
{
plugin.Calculate();
}
}
我只需要装饰 Calculator
属性:
[XmlElement("Multiple", typeof(Multiple))]
[XmlElement("Add", typeof(Add))]
[XmlElement("Subtract", typeof(Divide))]
[XmlElement("Divide", typeof(Divide))]
[XmlElement("Operator", typeof(Operand))]
最佳答案
我猜您想使用 XmlSerializer。 如果您需要“多态”反序列化,您可以传递序列化程序应该知道的类型列表(如果它们都继承自相同的基类而不是接口(interface),则此方法有效)。
例子:
List<Type> extraTypes = new List<Type>();
extraTypes.Add(typeof(multiple));
extraTypes.Add(typeof(add));
extraTypes.Add(typeof(substract));
extraTypes.Add(typeof(divide));
var ser = new XmlSerializer(typeof(Foo), extraTypes.ToArray());
解释如下: Serializing and restoring an unknown class
但是还有另一个问题,在您的 XML 中,您的操作数可以包含两种不同的类型:一个操作或一个参数(a、b、c、d),您不能在您的类中表示它。
我经常看到的是这样的(我只实现了加操作,我假设表达式是数字):
public class Expression
{
public virtual int Evaluate()
{
}
}
public class Add : Expression
{
Expression _left;
Expression _right;
public Add(Expression left, Expression right)
{
_left = left;
_right = right;
}
override int Evalute()
{
return _left.Evalute() + _right.Evalute();
}
}
public class Parameter : Expression
{
public int Value{get;set;}
public Parameter(string name)
{
// Use the name however you need.
}
override int Evalute()
{
return Value;
}
}
这样你只有一个基类所以一切都更简单。如果这有意义,我想反序列化它不会很难。
编辑: 如果基类是计算器(而不是表达式),XML 将如下所示:
<Calculator xsi:type="Multiple">
<calculators>
<Calculator xsi:type="Add">
<calculators>
<Calculator xsi:type="Operator">
<value>12</value>
</Calculator>
</calculators>
</Calculator>
</calculators>
</Calculator>
我创建了一个简单的计算器对象并将其序列化,这就是我得到的。如果你反序列化它,你会得到一个返回 12 的计算器。
也许您可以使用 XmlAttributes 更改 XML 中元素的名称,或者在最坏的情况下编写您自己的反序列化程序。
关于c# - 使用 C# 将 xml 反序列化为父类(super class)对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17292634/