【问题标题】:Having trouble getting a class to serialize无法让类序列化
【发布时间】:2014-12-23 02:05:18
【问题描述】:

我正在使用 xml 序列化程序,我正在尝试序列化一个类。 xml 为以下类提供了一个空节点。当我将键和值列表设置为公开时,统一冻结。

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Grimoire.Tools.CerealTools
{
    [Serializable]
    public class CerealDictionary<Key, Value> //: IEnumerable
        {
        [SerializeField]
        private List<Key> keys = new List<Key>();
        [SerializeField]
        private List<Value> values = new List<Value>();
        public CerealDictionary(){}
        public Value this[Key k]
            {
            get
                {
                int count = keys.IndexOf(k);
                return values[count];
                }//getters and setters for indexers :)
            set
                {
                int count = keys.IndexOf(k);
                if (count>-1){values[count]=value;}
                else//if the index doesnt exist, then we should make a new one :)
                    {
                    values.Add(value);
                    keys.Add(k);
                    }
                }
            }
        public void Add(Key key, Value value)
            {
            //if (keys.Contains(key)){return;}
            keys.Add(key);
            values.Add(value);
            }
        public void Remove(Key key)
            {
            if (!keys.Contains(key)){return;}
            int index = keys.IndexOf(key);
            keys.RemoveAt(index);
            values.RemoveAt(index);
            }
        public bool TryGetValue(Key key, out Value value)
            {
            if (keys.Count != values.Count)
                {
                keys.Clear();
                values.Clear();
                value = default(Value);
                return false;
                }
            if (!keys.Contains(key))
                {
                value = default(Value);
                return false;
                }
            int index = keys.IndexOf(key);
            value = values[index];
            return true;
            }
        public bool TryGetKey(Value value, out Key key)
            {
            if (keys.Count != values.Count)
                {
                values.Clear();
                keys.Clear();
                key = default(Key);
                return false;
                }
            if (!values.Contains(value))
                {
                key = default(Key);
                return false;
                }
            int index = values.IndexOf(value);
            key = keys[index];
            return true;
            }
        public bool getGroup(Key key, out List<Value> thisValues)
            {
            thisValues = new List<Value>();
            if (keys.IndexOf(key)==-1){return false;}
            foreach(Key keyTemp in keys)
                {
                int index = keys.IndexOf(keyTemp);
                thisValues.Add(values[index]);
                }
            return true;
            }
        public void ChangeValue(Key key, Value value)
            {
            if (!keys.Contains(key)){return;}
            int index = keys.IndexOf(key);
            values[index] = value;
            }
        public int length()
            {
            return keys.Count;
            }
//      IEnumerator IEnumerable.GetEnumerator()
//          {
//          return getEnumerator(keys,values);
//          }
//      private Grimoire.Tools.CerealTools.CerealDictionaryEnumerator<Value> getEnumerator()
//          {
//          return new CerealDictionaryEnumerator<Value>(values);
//          }
    }
}

这是序列化我的类的代码。

using UnityEngine;
using System.Collections;
using System.Xml.Serialization;
using System.IO;
public class StringSerializer {//for object to string serialization
    public static string convertToString<t>(t workObject)
        {//changes object to string
        XmlSerializer xmlSerializer = new XmlSerializer(workObject.GetType());
        StringWriter stringWriter = new StringWriter();
        xmlSerializer.Serialize(stringWriter,workObject);
        return stringWriter.ToString();
        }
    public static t convertFromString<t>(System.Type buildType,string buildString)
        {
        TextReader stringReader = new StringReader(buildString);
        XmlSerializer xmlSerlializer = new XmlSerializer(buildType);
        return (t)xmlSerlializer.Deserialize(stringReader);
        }
}

这是被序列化的类。它正在使用带有空白节点的类。

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
[Serializable]
public class ExampleBoard : IBoardData {
    public override List<Piece> pieces { get;set;}//position number, game piece
    public override Grimoire.Tools.CerealTools.CerealDictionary<int,BookInformation> books {get;set;}//number of books, book number
    public override Grimoire.Tools.CerealTools.CerealDictionary<int,int> rooms {get;set;}//position, room number. It details the relationship between positions and rooms
    public override Grimoire.Tools.Vector2 boardDimensions{get;set;}
    public override Grimoire.Tools.Vector2 boardSize{get;set;}
    public override int bookTotal{get;set;}
    public override int roomSize{get;set;}
    public ExampleBoard(){}//serialization....sigh
    public override void set()
        {
        boardDimensions = new Grimoire.Tools.Vector2(2,2);
        boardSize = new Grimoire.Tools.Vector2(968,968);
        roomSize = 484;
        books = new Grimoire.Tools.CerealTools.CerealDictionary<int,BookInformation> ();
        populateBooks ();
        bookTotal = books.length();
        pieces = new List<Piece> ();
        populatePieces ();
        rooms = new Grimoire.Tools.CerealTools.CerealDictionary<int, int> ();
        populateRoom (boardSize);
        }
    public override void saveSize(Grimoire.Tools.Vector2 size)
        {
        populateRoom (size);
        boardSize = getBoardSize(size);
        boardDimensions = size;
        }
    private Grimoire.Tools.Vector2 getBoardSize(Grimoire.Tools.Vector2 size)
        {
        return new Grimoire.Tools.Vector2((float)(size.x*roomSize),(float)((size.y*roomSize)));
        }
    public override void save(){}// needs to be here.
    private void populateRoom(Grimoire.Tools.Vector2 size)//position number, room number
        {
        int count = (int)(size.x*size.y);
        double roomCount = 0;
        int positionCount = -1;
        for(int i=0;i<count;i++)
            {
            roomCount += 0.25;
            positionCount +=1;
            rooms.Add((int)roomCount,positionCount);
            }
        }
    private void populateBooks()// number of books, book name.
        {
        books.Add (1,new BookInformation(9,0,1));
        books.Add (2,new BookInformation(9,1,2));
        books.Add (3,new BookInformation(9,2,3));
        books.Add (4,new BookInformation(9,3,4));
        books.Add (5,new BookInformation(9,4,5));
        books.Add (6,new BookInformation(9,5,6));
        books.Add (7,new BookInformation(9,6,7));
        books.Add (8,new BookInformation(9,7,8));
        books.Add (9,new BookInformation(9,8,9));
        }
    public override int getBookPosition(int bookNumber)
        {
        for(int i=1;i<books.length()+1;i++)
            {
            if (books[i].type==bookNumber){return books[i].key;}
            }
        return 0;
        }
    private void populatePieces()// piece position, piece. Change the pieces to something else later
        {
        pieces.Add (new Piece(1,"start",-1f));//start
        pieces.Add (new Piece(1,"apprentice",-1.1f));//player
        //_pieces.Add (new Piece(2,"apprentice",-1.1f));
        pieces.Add (new Piece(7,"right wall",-1f));//a box maybe
        pieces.Add (new Piece(8,"exit",-1f));//exit
        pieces.Add (new Piece(13,"gargoyle",-1.1f));
        }
    public override int getRoomFromPosition(int position)
        {
        int room;
        rooms.TryGetKey(position-1,out room);
        return room;
        }
}

这是 xml 输出。书籍和房间的收藏是空白的。

<?xml version="1.0" encoding="utf-16"?>
<Level xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <position>
    <x>0</x>
    <y>0</y>
    <z>0</z>
  </position>
  <name>0</name>
  <unlocked>true</unlocked>
  <starTotal>0</starTotal>
  <difficulty>0</difficulty>
  <size>
    <x>0</x>
    <y>0</y>
  </size>
  <board xsi:type="ExampleBoard">
    <pieces>
      <Piece>
        <position>1</position>
        <name>start</name>
        <z>-1</z>
      </Piece>
      <Piece>
        <position>1</position>
        <name>apprentice</name>
        <z>-1.1</z>
      </Piece>
      <Piece>
        <position>7</position>
        <name>right wall</name>
        <z>-1</z>
      </Piece>
      <Piece>
        <position>8</position>
        <name>exit</name>
        <z>-1</z>
      </Piece>
      <Piece>
        <position>13</position>
        <name>gargoyle</name>
        <z>-1.1</z>
      </Piece>
    </pieces>
    <books />
    <rooms />
    <boardDimensions>
      <x>2</x>
      <y>2</y>
    </boardDimensions>
    <boardSize>
      <x>968</x>
      <y>968</y>
    </boardSize>
    <bookTotal>9</bookTotal>
    <roomSize>484</roomSize>
  </board>
</Level>

这里是 IBoardData,被序列化的类派生自这个。

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Xml.Serialization;
[XmlInclude(typeof(ExampleBoard)),XmlInclude(typeof(LevelBoard))]
public abstract class IBoardData 
    {//this was an interface, but those cant be serialized easily
    [XmlIgnore]public virtual List<Piece> pieces { get{throw new UnityException("Class doesn't inherit pieces");}set{}}//position number, game piece
    [XmlIgnore]public virtual Grimoire.Tools.CerealTools.CerealDictionary<int,BookInformation> books { get{throw new UnityException("Class doesn't inherit books");}set{}}//number of books, book name
    [XmlIgnore]public virtual Grimoire.Tools.CerealTools.CerealDictionary<int,int> rooms{ get{throw new UnityException("Class doesn't inherit rooms");}set{}}
    public virtual void save(){throw new UnityException("Class doesn't inherit save");}
    [XmlIgnore]public virtual Grimoire.Tools.Vector2 boardDimensions{get{throw new UnityException("Class doesn't inherit boardDimensions");}set{}}
    [XmlIgnore]public virtual Grimoire.Tools.Vector2 boardSize{get{throw new UnityException("Class doesn't inherit boardSize");}set{}}
    [XmlIgnore]public virtual int bookTotal{get{throw new UnityException("Class doesn't inherit bookTotal");}set{}}
    public virtual int getRoomFromPosition(int pos){throw new UnityException("Class doesn't inherit getRoomPosition");}
    [XmlIgnore]public virtual int roomSize{get{throw new UnityException("Class doesn't inherit roomSize");}set{}}
    public virtual int getBookPosition(int bookNumber){throw new UnityException("Class doesn't inherit getBookPosition");}
    public virtual void saveSize(Grimoire.Tools.Vector2 size){throw new UnityException("Class doesn't inherit saveSize");}
    public virtual void set(){throw new UnityException("Class doesn't inherit set");}
    }

【问题讨论】:

  • 也许你应该展示你用来序列化的代码?因为那是冻结的代码?
  • 已编辑,添加了任何可能有用的内容。
  • 可能不是问题,但我相信XmlSerializer 不需要(实际上它忽略了)Serializable 属性
  • 您不能序列化私有字段。但是,当您将这些字段设置为公开时,您提到统一冻结。那是您应该尝试解决的问题吗?
  • btw,你不能使用.NET Framework提供的Dictionary类吗?

标签: c# xml serialization


【解决方案1】:

我昨天通过关闭和打开计算机解决了这个问题。我不知道问题是什么,但它可能是统一编译错误的某种问题,或者类似的问题。

【讨论】:

    猜你喜欢
    • 2019-08-11
    • 2018-05-09
    • 1970-01-01
    • 1970-01-01
    • 2015-12-21
    • 2016-04-23
    • 2016-08-22
    • 1970-01-01
    • 2010-12-10
    相关资源
    最近更新 更多