我正在创建一个程序,允许用户使用基本操作定义公式:使用
XML进行加,减,除,多.让我们举一个例子:用户想要定义像(a b)x(c d)这样的公式. xml的格式如下:
编辑我实现了这一点
<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(Subtract))] [XmlElement("Divide",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(); } }
[XmlElement("Multiple",typeof(Multiple))] [XmlElement("Add",typeof(Add))] [XmlElement("Subtract",typeof(Divide))] [XmlElement("Divide",typeof(Divide))] [XmlElement("Operator",typeof(Operand))]
解决方法
我猜你想要使用XmlSerializer.
如果需要“多态”反序列化,则可以传递序列化程序应该知道的类型列表(如果它们都从相同的基类继承而不是从接口继承,则可以使用).
如果需要“多态”反序列化,则可以传递序列化程序应该知道的类型列表(如果它们都从相同的基类继承而不是从接口继承,则可以使用).
例:
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; } }
这样你只有一个基类,所以一切都更简单.如果这有意义,我想将其反序列化并不困难.
编辑:
如果基类是Calculator(而不是Expression),则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中元素的名称,或者在最坏的情况下编写自己的反序列化器.