C#:手动读取派生类的XML配置
假设我有课堂资源, 类别赛车资源:公共赛车资源, 和SuperDuperUltraRaceCarResource类:公共赛车资源 我希望能够使用LoadFromXML的单个方法加载他们的数据 我如何获取CarResource:LoadFromXML来加载其数据, RaceCarResource调用CarResource:LoadFromXML,然后加载它自己的附加数据,等等 如果我使用XmlTextReader,我只知道如何一次性解析整个文件, 不是如何使用它,所以首先CarResource:LoadFromXML可以完成它的工作,然后RaceCarResource,等等 我希望我的意思至少有一点清楚:) ……等等。new关键字将隐藏继承的方法,但仍然允许从子类调用它 至于实际解析XML,您有两个选择。我的第一个建议是将整个XML文件读入内存…然后使用LINQtoXML解析并填充类。您还可以尝试XmlSerializer(LINQ to XML更容易实现,但随着代码库的增长,XML序列化可以使维护更容易) ……等等。new关键字将隐藏继承的方法,但仍然允许从子类调用它C#:手动读取派生类的XML配置,c#,xml,serialization,manual,derived,C#,Xml,Serialization,Manual,Derived,假设我有课堂资源, 类别赛车资源:公共赛车资源, 和SuperDuperUltraRaceCarResource类:公共赛车资源 我希望能够使用LoadFromXML的单个方法加载他们的数据 我如何获取CarResource:LoadFromXML来加载其数据, RaceCarResource调用CarResource:LoadFromXML,然后加载它自己的附加数据,等等 如果我使用XmlTextReader,我只知道如何一次性解析整个文件, 不是如何使用它,所以首先CarResource:L
至于实际解析XML,您有两个选择。我的第一个建议是将整个XML文件读入内存…然后使用LINQtoXML解析并填充类。您还可以尝试XmlSerializer(LINQ to XML更容易实现,但随着代码库的增长,XML序列化可以使维护更容易) 根据要从中加载的XML文件的结构,还可以使用XML序列化。可以重写load方法(然后在后续类中重写)来加载特定信息,或者只使用属性。请参阅:根据要从中加载的XML文件的结构,还可以使用XML序列化。可以重写load方法(然后在后续类中重写)来加载特定信息,或者只使用属性。请参阅:您有两个选择 您可以使用Linq to XML查询子实体,并将这些节点传递给其他类。这可能是最有效的方法 您可以使用xmlnavigator,再次只传递适当的子节点。。。 见:
您可以简单地使用xml序列化(XmlSerialize XmlDeserialize),请参见您有两个选项 您可以使用Linq to XML查询子实体,并将这些节点传递给其他类。这可能是最有效的方法 您可以使用xmlnavigator,再次只传递适当的子节点。。。 见:
您可以简单地使用xml序列化(XmlSerialize XmlDeserialize),请参见为了使用xml反序列化,实例方法使当前对象有效地“不可变”,但我建议如下:
public class CarResource
{
public CarResource LoadNewFromXML(string xml)
{
XmlSerializer ser = new XmlSerializer(this.GetType());
object o = null;
using (MemoryStream ms = new MemoryStream(Encoding.ASCII.GetBytes(xml)))
{
o = ser.Deserialize(ms);
}
return o as CarResource;
}
}
public class RaceCarResource : CarResource
{
}
public class SuperRaceCarResource : RaceCarResource
{
}
您的呼叫代码如下所示:
RaceCarResource car = new RaceCarResource();
car = car.LoadNewFromXML("<RaceCarResource/>") as RaceCarResource;
SuperRaceCarResource sc = new SuperRaceCarResource();
sc = sc.LoadNewFromXML("<SuperRaceCarResource/>") as SuperRaceCarResource;
RaceCarResource车=新的RaceCarResource();
car=car.LoadNewFromXML(“”)作为RaceCarResource;
SuperRaceCarResource sc=新的SuperRaceCarResource();
sc=sc.LoadNewFromXML(“”)作为SuperRaceCarResource;
为了使用XML反序列化,实例方法使当前对象有效地“不可变”,但我建议如下:
public class CarResource
{
public CarResource LoadNewFromXML(string xml)
{
XmlSerializer ser = new XmlSerializer(this.GetType());
object o = null;
using (MemoryStream ms = new MemoryStream(Encoding.ASCII.GetBytes(xml)))
{
o = ser.Deserialize(ms);
}
return o as CarResource;
}
}
public class RaceCarResource : CarResource
{
}
public class SuperRaceCarResource : RaceCarResource
{
}
您的呼叫代码如下所示:
RaceCarResource car = new RaceCarResource();
car = car.LoadNewFromXML("<RaceCarResource/>") as RaceCarResource;
SuperRaceCarResource sc = new SuperRaceCarResource();
sc = sc.LoadNewFromXML("<SuperRaceCarResource/>") as SuperRaceCarResource;
RaceCarResource车=新的RaceCarResource();
car=car.LoadNewFromXML(“”)作为RaceCarResource;
SuperRaceCarResource sc=新的SuperRaceCarResource();
sc=sc.LoadNewFromXML(“”)作为SuperRaceCarResource;
如果您的XML与.net XML序列化不兼容,那么最简单的方法是创建一个工厂,检测XML代表的资源类型,然后进行适当的处理。如果要将解析放入对象中,则在创建对象后使用虚拟方法解析内部构件:
class CarResource
{
public string Color { get; private set; }
internal virtual void ReadFrom(XmlReader xml)
{
this.Color = xml.GetAttribute("colour");
}
}
class RaceCarResource : CarResource
{
public string Sponsor { get; private set; }
internal override void ReadFrom(XmlReader xml)
{
base.ReadFrom(xml);
this.Sponsor = xml.GetAttribute("name-on-adverts");
}
}
class SuperDuperUltraRaceCarResource : RaceCarResource
{
public string Super { get; private set; }
internal override void ReadFrom(XmlReader xml)
{
base.ReadFrom(xml);
this.Super = xml.GetAttribute("soup");
}
}
class CarResourceFactory
{
public CarResource Read(XmlReader xml)
{
CarResource car;
switch (xml.LocalName)
{
case "ordinary-car": car = new CarResource(); break;
case "racecar": car = new RaceCarResource(); break;
case "super_duper": car = new SuperDuperUltraRaceCarResource(); break;
default: throw new XmlException();
}
XmlReader sub = xml.ReadSubtree();
car.ReadFrom(sub);
sub.Close();
return car;
}
}
如果子类型的XML有任何子元素严格地附加在超级类型的内容之后或之前,则这种方法可以正常工作。否则,您必须做更多的工作来重用超级类型的序列化,将其分解为更小的方法(例如,如果用于赛车的XML在车门和车轮数据之间包含机翼数据,则基础具有加载车轮数量、车门和发动机尺寸的方法;赛车调用LoadDoor data
,LoadAeroFoilData
,LoadWheelData
。对于没有逻辑顺序的格式(XMI,RDF)你必须检查本地名称来决定调用哪个专门的方法,如果你想将它与虚拟方法结合起来,这会有点混乱。在这种情况下,最好使用一个单独的序列化助手
如果要创建的类型集不固定为少数类型,则可以在工厂中使用其他机制。如果您的XML与.net XML序列化不兼容,则最简单的方法是创建一个工厂,该工厂检测XML表示的资源类型,然后适当地处理该类型。如果要将解析放入创建对象后,使用虚拟方法解析内部构件:
class CarResource
{
public string Color { get; private set; }
internal virtual void ReadFrom(XmlReader xml)
{
this.Color = xml.GetAttribute("colour");
}
}
class RaceCarResource : CarResource
{
public string Sponsor { get; private set; }
internal override void ReadFrom(XmlReader xml)
{
base.ReadFrom(xml);
this.Sponsor = xml.GetAttribute("name-on-adverts");
}
}
class SuperDuperUltraRaceCarResource : RaceCarResource
{
public string Super { get; private set; }
internal override void ReadFrom(XmlReader xml)
{
base.ReadFrom(xml);
this.Super = xml.GetAttribute("soup");
}
}
class CarResourceFactory
{
public CarResource Read(XmlReader xml)
{
CarResource car;
switch (xml.LocalName)
{
case "ordinary-car": car = new CarResource(); break;
case "racecar": car = new RaceCarResource(); break;
case "super_duper": car = new SuperDuperUltraRaceCarResource(); break;
default: throw new XmlException();
}
XmlReader sub = xml.ReadSubtree();
car.ReadFrom(sub);
sub.Close();
return car;
}
}
如果子类型的XML在超级类型的内容之后或之前添加了任何子元素,那么这就可以了。否则,您必须做更多的工作来重用超级类型的序列化,将其分解为更小的方法(例如,如果用于赛车的XML在车门和车轮数据之间包含机翼数据,则基础具有加载车轮数量、车门和发动机尺寸的方法;赛车调用LoadDoor data
,LoadAeroFoilData
,LoadWheelData
。对于没有逻辑顺序的格式(XMI,RDF)您必须检查本地名称以决定调用哪个专门方法,如果您想使用c,这会有点混乱