如何使用带有层次结构类结构的 C# 反序列化

发布于 2024-10-17 10:04:26 字数 1342 浏览 4 评论 0原文

我正在尝试将一些 xml 文件反序列化为一些已简化为以下内容的类:

[XmlRoot("person")]
[Serializable]
public class Person
{
    [XmlElement]
    public Toy Toy { get; set; }
}

[Serializable]
public class ActionMan : Toy
{
    [XmlElement("guns")]
    public string Guns;
}

[Serializable]

public class Doll : Toy
{
    [XmlElement("name")]
    public  String Name;
}

[XmlInclude(typeof(Doll))]
[XmlInclude(typeof(ActionMan))]
public class Toy
{
}

[TestFixture]
public class ToyTest
{
    [Test]
    public void testHierarchy()
    {
        String filePath = @"test\brother.xml";
        String sisfilePath = @"test\sister.xml";
        var serializer = new XmlSerializer(typeof(Person));
        Person brother = (Person)serializer.Deserialize(new FileStream(filePath, FileMode.Open));
        Person sister = (Person)serializer.Deserialize(new FileStream(sisfilePath, FileMode.Open));

        Assert.IsNotNull(brother);
        Assert.IsNotNull(sister);
        Assert.IsAssignableFrom(typeof(ActionMan),brother.Toy);
        Assert.IsAssignableFrom(typeof(Doll),sister.Toy);
    }
}

我想使用 c# 序列化(我知道我可以使用我自己的反序列化器),并且我认为我可能只是缺少一个特定的标记我不知道(而且我确信我有多余的标签)。

这是 xml 文件之一:

<person>
  <doll>
    <name>Jill</name>
  </doll>
</person>

我得到的错误是“预期:可从第三个断言上分配”

I'm trying to deserialize some xml files into some classes which have been simplified to the following:

[XmlRoot("person")]
[Serializable]
public class Person
{
    [XmlElement]
    public Toy Toy { get; set; }
}

[Serializable]
public class ActionMan : Toy
{
    [XmlElement("guns")]
    public string Guns;
}

[Serializable]

public class Doll : Toy
{
    [XmlElement("name")]
    public  String Name;
}

[XmlInclude(typeof(Doll))]
[XmlInclude(typeof(ActionMan))]
public class Toy
{
}

[TestFixture]
public class ToyTest
{
    [Test]
    public void testHierarchy()
    {
        String filePath = @"test\brother.xml";
        String sisfilePath = @"test\sister.xml";
        var serializer = new XmlSerializer(typeof(Person));
        Person brother = (Person)serializer.Deserialize(new FileStream(filePath, FileMode.Open));
        Person sister = (Person)serializer.Deserialize(new FileStream(sisfilePath, FileMode.Open));

        Assert.IsNotNull(brother);
        Assert.IsNotNull(sister);
        Assert.IsAssignableFrom(typeof(ActionMan),brother.Toy);
        Assert.IsAssignableFrom(typeof(Doll),sister.Toy);
    }
}

I want to use the c# Serialisation (I know I can use my own deserialiser) and I think I'm perhaps simply missing a particular tag that I don't know about (and I'm sure I've got superfluous tags).

here is one fo the xml files:

<person>
  <doll>
    <name>Jill</name>
  </doll>
</person>

the error I get is "Expected: assignable from " on the third assert

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

旧城烟雨 2024-10-24 10:04:27

当我尝试序列化你的结构(人,以 ActionMan 作为玩具)时,我得到

<前><代码><人>;
<玩具 xsi:type="ActionMan" />

我想这就是您处理类型继承的方式。
但我猜你无法更改已经序列化的 XML。

When I try to serialize your structure (person, who has ActionMan as Toy) i get

<person>
  <Toy xsi:type="ActionMan" />
</person>

I guess this is how you can handle inheritance of your types.
But I guess you cant change your already serialised XML.

魔法唧唧 2024-10-24 10:04:27

我所做的就是按照我想要的方式设计类结构,填充一些基本数据,然后将其序列化。然后检查它如何序列化并调整 Xml 属性。如果您的 Toy 类只有几个派生类,那么您可以使用 action-man 字段和 doll 字段(可能为空或不为空)分别对它们进行反序列化。

或者,为了从 Xml 文件转到 ac# 类,我使用 xsd.exe 工具使用 xsd mydata.xml 生成 .xsd 文件然后从该 ac# 类文件中使用 xsd /c /l:cs mydata.xsd。然后,我检查类数据,以获取有关如何定义类以及要使用哪些属性的线索。

链接到 Microsoft 的 xsd 工具。

What I have done, is designed the class structure the way I want, fill in some basic data and then serialize it. Then examine how it serializes and adjust the Xml attributes. If your Toy class has only a few derivatives, then you can de-serialize them seperately with a action-man field and a doll field that might be null or not.

Alternatively to go from an Xml file to a c# class I use the xsd.exe tool to generate a .xsd file with xsd mydata.xml and then from that a c# class file with xsd /c /l:cs mydata.xsd. Then I examine the class data to get clues as to how to define my class and what attributes to use.

link to xsd tool from Microsoft.

如歌彻婉言 2024-10-24 10:04:27

尝试以下操作

public class Person 
{

    public Toy toy
    {
        get
        {
            return (doll == null) ? (Toy)actionMan : (Toy)doll;
        }

    }


    public Doll doll;
    public ActionMan actionMan;
}


public class Toy 
{

}


public class Doll : Toy
{
    public String name;

}


public class ActionMan : Toy
{
    public String guns;
}

class Program
{
    static void Main(string[] args)
    {

        Person brother = new Person();
        ActionMan am = new ActionMan();
        am.guns = "Laser Beam";
        brother.actionMan = am;

        Person sister = new Person();
        Doll d = new Doll();
        d.name = "Jill";
        sister.doll = d;

        Serialize(brother, "brother.xml");
        Serialize(sister, "sister.xml");

        Person b = Deserialize("brother.xml");
        Person s = Deserialize("sister.xml");

        Console.WriteLine(((ActionMan)b.toy).guns);
        Console.WriteLine(((Doll)s.toy).name);
        Console.Read();
    }

    public static Person Deserialize(String filename)
    {
        var serializer = new XmlSerializer(typeof(Person));
        return (Person)serializer.Deserialize(new FileStream(filename, FileMode.Open));

    }

    public static void Serialize(Person p, String filename){
        Stream stream = File.Open(filename, FileMode.Create);
        XmlSerializer s = new XmlSerializer(typeof(Person));
        s.Serialize(stream, p);
        stream.Close();

    }

您可以从这里扩展。请记住,在属性名称中,大小写很重要。 序列化输出是

Brother.xmlister.xml

<?xml version="1.0"?>
<Person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <actionMan>
    <guns>Laser Beam</guns>
  </actionMan>
</Person>

我得到的

<?xml version="1.0"?>
<Person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <doll>
    <name>Jill</name>
  </doll>
</Person>

输出是

Laser Beam
Jill

Try the following

public class Person 
{

    public Toy toy
    {
        get
        {
            return (doll == null) ? (Toy)actionMan : (Toy)doll;
        }

    }


    public Doll doll;
    public ActionMan actionMan;
}


public class Toy 
{

}


public class Doll : Toy
{
    public String name;

}


public class ActionMan : Toy
{
    public String guns;
}

class Program
{
    static void Main(string[] args)
    {

        Person brother = new Person();
        ActionMan am = new ActionMan();
        am.guns = "Laser Beam";
        brother.actionMan = am;

        Person sister = new Person();
        Doll d = new Doll();
        d.name = "Jill";
        sister.doll = d;

        Serialize(brother, "brother.xml");
        Serialize(sister, "sister.xml");

        Person b = Deserialize("brother.xml");
        Person s = Deserialize("sister.xml");

        Console.WriteLine(((ActionMan)b.toy).guns);
        Console.WriteLine(((Doll)s.toy).name);
        Console.Read();
    }

    public static Person Deserialize(String filename)
    {
        var serializer = new XmlSerializer(typeof(Person));
        return (Person)serializer.Deserialize(new FileStream(filename, FileMode.Open));

    }

    public static void Serialize(Person p, String filename){
        Stream stream = File.Open(filename, FileMode.Create);
        XmlSerializer s = new XmlSerializer(typeof(Person));
        s.Serialize(stream, p);
        stream.Close();

    }

You can expand from here. Remember that, in the attribute names, casing matters. The serialization output I got is

brother.xml

<?xml version="1.0"?>
<Person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <actionMan>
    <guns>Laser Beam</guns>
  </actionMan>
</Person>

sister.xml

<?xml version="1.0"?>
<Person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <doll>
    <name>Jill</name>
  </doll>
</Person>

The output is

Laser Beam
Jill
自此以后,行同陌路 2024-10-24 10:04:26

类 person 应该包含“娃娃”属性而不是“玩具”属性,我的意思是名称。 XML 节点的名称必须与属性名称相同 - 大小写很重要。

Class person should contain a "doll" attribute instead of a "Toy" attribute, I mean the name. The XML node must have the same name as the attribute name -casing matters.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文