使用相同类型名称的结构序列化类

时间:2015-04-20 23:28:32

标签: c# xml-serialization

我正在尝试XML序列化一个包含两个具有相同名称的结构的类:

public class MyClass 
{
  public System.Windows.Size WSize = new System.Windows.Size();
  public System.Drawing.Size DSize = new Size.Drawing.Size();
}

产生的错误:

Types 'System.Drawing.Size' and 'System.Windows.Size' both use the XML type name, 
'Size', from namespace ''. Use XML attributes to specify a unique XML name and/or 
namespace for the type.

到目前为止我发现的所有内容都涉及使用XML属性来装饰Type。我不能直接装饰任何结构,因为它们不是我的代码。

我觉得我在这里很容易丢失一些东西......是否有可以应用于字段的XML属性?

修改 我使用几个代理属性添加了答案。我对这个特定的实施不满意,因为它让公共财产停滞不前。

我也考虑过DataContractSerialization,但我还是犹豫不决下一步。其他人有他们可以建议的东西吗?

编辑2 我的措辞可能有些混乱。我可以修改和修饰MyClassWSizeDSize。但是,显然,我无法修改System.Windows.SizeSystem.Drawing.Size

3 个答案:

答案 0 :(得分:2)

你可以通过自定义XML序列化的代理来完成,我创建了这个完全有效的例子,虽然有很多错误检查要完成它的起点。

public class MyClass
{
    public System.Windows.Size WSize = new System.Windows.Size();
    public System.Drawing.Size DSize = new System.Drawing.Size();
}

public class MyClassProxy : MyClass, IXmlSerializable
{
    public new System.Windows.Size WSize { get { return base.WSize; } set { base.WSize = value; } }
    public new System.Drawing.Size DSize { get { return base.DSize; } set { base.DSize = value; } }

    public System.Xml.Schema.XmlSchema GetSchema()
    {
        return null;
    }

    public void ReadXml(System.Xml.XmlReader reader)
    {
        reader.MoveToContent();
        reader.ReadStartElement();
        string wheight = reader["height"];
        string wwidth = reader["width"];
        int w, h;
        w = int.Parse(wwidth);
        h = int.Parse(wheight);
        WSize = new Size(w, h);
        reader.ReadStartElement();
        string dheight = reader["height"];
        string dwidth = reader["width"];
        w = int.Parse(dwidth);
        h = int.Parse(dheight);
        DSize = new System.Drawing.Size(w, h);
    }

    public void WriteXml(System.Xml.XmlWriter writer)
    {
        writer.WriteStartElement("MyClassProxy");
        writer.WriteStartElement("WSize");
        writer.WriteAttributeString("height", WSize.Height.ToString());
        writer.WriteAttributeString("width", WSize.Width.ToString());
        writer.WriteEndElement();
        writer.WriteStartElement("DSize");
        writer.WriteAttributeString("height", DSize.Height.ToString());
        writer.WriteAttributeString("width", DSize.Width.ToString());
        writer.WriteEndElement();
        writer.WriteEndElement();
    }
}

class Program
{
    static void Main(string[] args)
    {
        MyClassProxy p = new MyClassProxy();
        p.DSize = new System.Drawing.Size(100, 100);
        p.WSize = new Size(400, 400);

        string xml = "";

        using (StringWriter sw = new StringWriter())
        {
            System.Xml.XmlWriter wr = System.Xml.XmlWriter.Create(sw);
            p.WriteXml(wr);
            wr.Close();
            xml = sw.ToString();
        }

        MyClassProxy p2 = new MyClassProxy();

        using (StringReader sr = new StringReader(xml))
        {
            System.Xml.XmlReader r = System.Xml.XmlReader.Create(sr);
            p2.ReadXml(r);
        }

        MyClass baseClass = (MyClass)p2;

        Print(baseClass);

        Console.ReadKey();
    }

    static void Print(MyClass c)
    {
        Console.WriteLine(c.DSize.ToString());
        Console.WriteLine(c.WSize.ToString());
    }


}

答案 1 :(得分:0)

在这里,我可能并不十分满意(不是很干净):

public class MyClass 
{
  public System.Windows.Size WSize = new System.Windows.Size();

  [XmlIgnore]
  public System.Drawing.Size DSize = new Size();

  public int DSizeWidthForSerialization
  {
    get
    {
      return DSize.Width;
    }
    set
    {
      DSize.Width = value;
    }
  }
  public int DSizeHeightForSerialization
  {
    get
    {
      return DSize.Height;
    }
    set
    {
      DSize.Height = value;
    }
  }
}

答案 2 :(得分:0)

我最终创建了一个容纳System.Drawing.Size的新课程。在那个新类中,我创建了隐式运算符并处理了一些构造函数。这允许我序列化,而不必更改任何现有代码:

public class MyClass 
{
  public System.Windows.Size WSize = new System.Windows.Size();
  public MyDrawingSize DSize = new System.Drawing.Size();

  public class MyDrawingSize
  {
    public int Height, Width;

    public MyDrawingSize() { } //Needed for deserialization
    public MyDrawingSize(int width, int height)
    {
      Width = width;
      Height = height;
    }
    public static implicit operator System.Drawing.Size(MyDrawingSize size)
    {
      return new System.Drawing.Size(size.Width, size.Height);
    }
    public static implicit operator MyDrawingSize(System.Drawing.Size size)
    {
      return new MyDrawingSize() { Width = size.Width, Height = size.Height };
    }

  }
}