C#:手动读取派生类的XML配置

C#:手动读取派生类的XML配置,c#,xml,serialization,manual,derived,C#,Xml,Serialization,Manual,Derived,假设我有课堂资源, 类别赛车资源:公共赛车资源, 和SuperDuperUltraRaceCarResource类:公共赛车资源 我希望能够使用LoadFromXML的单个方法加载他们的数据 我如何获取CarResource:LoadFromXML来加载其数据, RaceCarResource调用CarResource:LoadFromXML,然后加载它自己的附加数据,等等 如果我使用XmlTextReader,我只知道如何一次性解析整个文件, 不是如何使用它,所以首先CarResource:L

假设我有课堂资源, 类别赛车资源:公共赛车资源, 和SuperDuperUltraRaceCarResource类:公共赛车资源

我希望能够使用LoadFromXML的单个方法加载他们的数据

我如何获取CarResource:LoadFromXML来加载其数据, RaceCarResource调用CarResource:LoadFromXML,然后加载它自己的附加数据,等等

如果我使用XmlTextReader,我只知道如何一次性解析整个文件, 不是如何使用它,所以首先CarResource:LoadFromXML可以完成它的工作,然后RaceCarResource,等等

我希望我的意思至少有一点清楚:)

……等等。new关键字将隐藏继承的方法,但仍然允许从子类调用它

至于实际解析XML,您有两个选择。我的第一个建议是将整个XML文件读入内存…然后使用LINQtoXML解析并填充类。您还可以尝试XmlSerializer(LINQ to XML更容易实现,但随着代码库的增长,XML序列化可以使维护更容易)

……等等。new关键字将隐藏继承的方法,但仍然允许从子类调用它


至于实际解析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,这会有点混乱