XML序列化类具有隐藏继承成员的新属性

时间:2016-03-10 23:52:21

标签: c# xml inheritance

我有以下抽象类结构:

while ($text =~ /$velar_velar/g) {

然后我将这些模板类用作模型的一部分:

public abstract class Template
{
   // Some properties and methods defined
}

public abstract class Template<TTemplate> : Template where TTemplate : Template
{
 // No new properties defined, but methods overriden
}

然后我创建了我的模板和模型的具体类,并在我的项目中使用它们。这些具体类定义了除抽象基类中指定的属性之外的其他属性。现在是时候序列化Model类了。我使用反射来查找所有继承的Model或Template类型,并将它们传递给XmlSerializer,以便它可以正确地序列化我的抽象类。但是,我得到了一个例外

public abstract class Model 
{
  public Template Template {get;set;}
  public Model(Template t) {Template = t;}
  // More properties and methods
}

public abstract class Model<TModel, TTemplate> : Model where TModel : Model where TTemplate : Template
{
  public new TTemplate template {get {return (TTemplate)base.Template;} set {base.Template = value;}}
  public Model(TTemplate t) : base(t) {}
  // Override some methods but no new properties
}

我从2003年开始this post on google groups,其意图是给出答案,但我不确定如何实施该修复(或者如果它在13年后有效)。它确实表明错误消息具有误导性,因为消息提出的解决方案不起作用。

如果我删除&#39;设置&#39;来自Model.Template和类型化Model类的访问器(例如,通过构造函数设置它),类序列化很好 - 尽管没有Template属性。有没有办法XML序列化类来隐藏(n)(抽象)基类的属性,而不是在每个继承的类上实现IXmlSerializable?

1 个答案:

答案 0 :(得分:5)

我通过david.woodward遇到this post,显示了处理这种情况的可行和on-the-rails方法(即,当更改基类不是一个选项时)。它建议向XmlAttributeOverrides提供XmlSerializer

使用提供的对象模型,以下代码说明了如何使用它。它的工作原理是明确告诉XmlSerializer忽略基类中的隐藏属性,在本例中为Model.Template

using System;
using System.IO;
using System.Text;
using System.Xml.Serialization;

class Program
{
    static void Main(string[] args)
    {
        ConcreteTemplate ct = new ConcreteTemplate() { SomeProperty = "hello" };
        ConcreteGenericModel cgm = new ConcreteGenericModel(ct);

        XmlAttributeOverrides attrOverides = new XmlAttributeOverrides();
        XmlAttributes attrs = new XmlAttributes() { XmlIgnore = true };
        attrOverides.Add(typeof(Model), "Template", attrs);

        Type[] extraTypes = new Type[0];
        XmlSerializer serializer = new XmlSerializer(typeof(ConcreteGenericModel), attrOverides, extraTypes, null, null);

        StringBuilder sb = new StringBuilder();
        using (StringWriter writer = new StringWriter(sb))
            serializer.Serialize(writer, cgm);
        string serializedClass = sb.ToString();

        Console.WriteLine(serializedClass);

        ConcreteGenericModel deserializedCgm;
        using (StringReader reader = new StringReader(serializedClass))
            deserializedCgm = (ConcreteGenericModel)serializer.Deserialize(reader);

        Console.ReadLine();
    }
}

public abstract class Template
{
    // Some properties and methods defined
    public virtual string SomeProperty { get; set; }
}

public abstract class Template<TTemplate> : Template where TTemplate : Template
{
    // No new properties defined, but methods overriden
}

public class ConcreteTemplate : Template { }

public abstract class Model
{
    public Model() { }
    public Template Template { get; set; }
    public Model(Template t) { Template = t; }
    // More properties and methods
}

public class ConcreteModel : Model
{
    public ConcreteModel(Template t) : base(t) { }
}

public abstract class Model<TModel, TTemplate> : Model
    where TModel : Model
    where TTemplate : Template
{
    public Model() { }
    public new TTemplate Template { get { return (TTemplate)base.Template; } set { base.Template = value; } }
    public Model(TTemplate t) : base(t) { }
    // Override some methods but no new properties
}

public class ConcreteGenericModel : Model<ConcreteModel, ConcreteTemplate>
{
    public ConcreteGenericModel() { }
    public ConcreteGenericModel(ConcreteTemplate t) : base(t) { }
}