Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 反序列化()不是';t反序列化列表<;T>;正确地_C#_.net_Xml Serialization - Fatal编程技术网

C# 反序列化()不是';t反序列化列表<;T>;正确地

C# 反序列化()不是';t反序列化列表<;T>;正确地,c#,.net,xml-serialization,C#,.net,Xml Serialization,我是C#XmlSerializer的新手,所以这里可能缺少一些基本的东西 我遇到的问题是,我有一个类有另一个类的列表。当我序列化主类时,XML看起来很漂亮,所有数据都完好无损。当我反序列化XML时,列表中的数据消失,剩下一个空的列表。我没有收到任何错误,序列化部分工作正常 反序列化过程中我遗漏了什么 编辑:请注意,下面显示的代码不会重现问题-它可以正常工作。这是真实代码的简化版本,不起作用。不幸的是,下面的代码被简化到无法再现问题 public class User { public Use

我是C#XmlSerializer的新手,所以这里可能缺少一些基本的东西

我遇到的问题是,我有一个类有另一个类的
列表。当我序列化主类时,XML看起来很漂亮,所有数据都完好无损。当我反序列化XML时,
列表
中的数据消失,剩下一个空的
列表
。我没有收到任何错误,序列化部分工作正常

反序列化过程中我遗漏了什么

编辑:请注意,下面显示的代码不会重现问题-它可以正常工作。这是真实代码的简化版本,不起作用。不幸的是,下面的代码被简化到无法再现问题

public class User
{
  public User()
  {
    this.Characters = new List<Character>();
  }
  public string Username { get; set; }
  public List<Character> Characters { get; set; }
}

public class Character
{
  public Character()
  {
    this.Skills = new List<Skill>();
  }
  public string Name { get; set; }
  public List<Skill> Skills { get; set; }
}

public enum Skill
{
  TreeClimber,
  ForkliftOperator
}

public static void Save(User user)
{
    using (var textWriter = new StreamWriter("data.xml"))
    {
        var xmlSerializer = new XmlSerializer(typeof(User));
        xmlSerializer.Serialize(textWriter, user);
    }
}

public static User Restore()
{
    if (!File.Exists("data.xml"))
        throw new FileNotFoundException("data.xml");

    using (var textReader = new StreamReader("data.xml"))
    {
        var xmlSerializer = new XmlSerializer(typeof(User));
        return (User)xmlSerializer.Deserialize(textReader);
    }
}

public void CreateAndSave()
{
  var character = new Character();
  character.Name = "Tranzor Z";
  character.Skills.Add(Skill.TreeClimber);

  var user = new User();
  user.Username = "Somebody";
  user.Characters.Add(character);

  Save(user);
}

public void RestoreAndPrint()
{
  var user = Restore();
  Console.WriteLine("Username: {0}", user.Username);
  Console.WriteLine("Characters: {0}", user.Characters.Count);
}

有人能给我解释一下为什么Characters属性被正确序列化但不能反序列化吗?

这可能与枚举的反序列化有关…因为它将其序列化为字符串值…可能无法为字符创建正确的枚举值。没有测试过这个假设…

Stream=File.Open(filename+“.xml”,FileMode.Open);
Stream stream = File.Open(filename + ".xml", FileMode.Open);
User user = null;
using (XmlReader reader = XmlReader.Create(stream))
{
    user = IntermediateSerializer.Deserialize<User>(reader, null);
}
stream.Close();

return user;
User=null; 使用(XmlReader=XmlReader.Create(stream)) { user=IntermediateSerializer.Deserialize(读取器,null); } stream.Close(); 返回用户;
我会尝试使用类似的东西。

无法复制;我得到(在修复了更直接的bug之后):

变化:

  • WriteLine
    而不是
    WriteFormat
    (这阻止了它的编译)
  • 初始化默认构造函数中的列表(这会阻止
    CreateAndSave
    工作):
    • public User(){Characters=new List();}
    • public Character(){Skills=new List();}

过去,在序列化列表时,我使用了[XmlArray]和[XmlArrayItem]注释。然后在Characters属性上添加[XmlIgnore]注释。在您的情况下,它看起来是这样的:

[XmlArray("Characters")]
[XmlArrayItem("Character", Type=typeof(Character))]
public Character[] _ Characters
{
    get
    {
        //Make an array of Characters to return 
        return Characters.ToArray();
    }

    set
    {
        Characters.Clear();
        for( int i = 0; i < value.Length; i++ )
            Characters.Add( value[i] );
    }
}
[XmlArray(“字符”)]
[XmlArrayItem(“字符”,Type=typeof(字符))]
公共字符[]个字符
{
得到
{
//生成要返回的字符数组
返回字符。ToArray();
}
设置
{
字符。清除();
for(int i=0;i

希望这会有所帮助。

也许,可以创建一个XmlReader,而不是StreamReader。此外,作为故障排除步骤,您可以使用显式类型(如下所示)而不是“var”声明来尝试现有代码

public static User Restore()
{
  if (!File.Exists("data.xml"))
    throw new FileNotFoundException("data.xml");

  XmlReader xr = XmlReader.Create("data.xml");
  XmlSerializer serializer = new XmlSerializer(typeof(User));
  var user = (User)serializer.Deserialize(xr);
  xr.Close();
  return user;
}
编辑: 另外,在用户类上尝试XmlInclude注释

[XmlInclude( typeof( Character ) )]

在花了很长时间研究代码之后,我最终放弃了使用XmlSerializer的默认行为的想法


所有相关类现在都继承IXmlSerializer并实现ReadXml()和WriteXml()函数。我真的希望采用惰性路线,但现在我已经使用了IXmlSerializer,我意识到这真的一点都不困难,增加的灵活性也非常好。

我将此属性添加到我的列表类型中,然后它就起作用了(有你同样的问题):

[System.Xml.Serialization.xmlementAttribute(“NameOfMyField”)]
myfield{get;set;}的公共列表名称

我认为这是你的解决方案

我知道这很旧,但我也有同样的问题


我发现,如果我在图中有一个实现IXmlSerializable的对象(因此我想要反序列化的主对象没有实现接口,但其中的一个对象实现了接口),它会破坏所有反序列化。列表不再反序列化,我所说的对象也不再反序列化。序列化工作得非常完美。

类型上不需要[Serializable]。Xml序列化程序的行为完全独立于该属性。OK;因此,由于我们(或至少我)怀疑问题出在“真实”代码中(未显示);您在列表的“set”访问器中做了什么有趣的事情吗?那将是我首先要看的地方。不,它们都是基本属性,在get或set访问器中没有什么特别之处。它们看起来都有点像:public T PropertyName{get;set;}甚至对于列表?i、 公共列表PropName{get;set;}?即使对于列表也是如此。不过,我在列表中使用公共setter的唯一原因是用于反序列化程序。如果setter是私有的,那么XmlSerializer抛出InvalidOperationException,抱怨只读字符属性。Hrm。。。我上面发布的代码是模仿我真实代码的示例代码,因此我犯了错误,抱歉。我的实际项目要大得多,但发布的代码与我要做的事情非常接近。我的意图是提供一个代表我的情况的例子,而不是提供所有血淋淋的细节/不幸的是,我认为问题出在被省略的代码中。我会看一看protobuf net,但我的目标是一种人类可读/可编辑的格式,可以用任何基本的文本编辑器进行操作。我正在使用的代码与游戏相关,但我没有在这个项目中引用XNA框架,因此我无法访问IntermediateSerializer。对不起,在我的实际代码项目中,根类确实有其他正确序列化和反序列化的枚举。我也可以成功地序列化和反序列化字符列表中的各个对象。只有在反序列化用户对象时,进程才会崩溃,字符列表为空,并且不会引发异常。-1:枚举没有问题。我建议以后要么测试,要么什么都不说。运气不好——我得到的结果是一样的,也就是一个空列表。当我反序列化时,没有任何字符相关的代码被触动。信息技术
[XmlArray("Characters")]
[XmlArrayItem("Character", Type=typeof(Character))]
public Character[] _ Characters
{
    get
    {
        //Make an array of Characters to return 
        return Characters.ToArray();
    }

    set
    {
        Characters.Clear();
        for( int i = 0; i < value.Length; i++ )
            Characters.Add( value[i] );
    }
}
public static User Restore()
{
  if (!File.Exists("data.xml"))
    throw new FileNotFoundException("data.xml");

  XmlReader xr = XmlReader.Create("data.xml");
  XmlSerializer serializer = new XmlSerializer(typeof(User));
  var user = (User)serializer.Deserialize(xr);
  xr.Close();
  return user;
}
[XmlInclude( typeof( Character ) )]
[System.Xml.Serialization.XmlElementAttribute("NameOfMyField")]
public List<SomeType> NameOfMyField{get;set;}