XML使用新属性序列化类,该属性隐藏继承的成员

mma*_*his 5 c# xml inheritance

我有以下抽象类的结构:

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
}
Run Code Online (Sandbox Code Playgroud)

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

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
}
Run Code Online (Sandbox Code Playgroud)

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

There was an error reflecting type 'ConcreteModel'. ---> 
System.InvalidOperationException: There was an error reflecting property 
'Template'. ---> System.InvalidOperationException: Member 
ModelOfConcreteModelConcreteTemplate.Template of type ConcreteTemplate hides 
base class member Model.Template of type Template. Use XmlElementAttribute 
or XmlAttributeAttribute to specify a new name.
Run Code Online (Sandbox Code Playgroud)

我在2003 年的Google网上论坛上看到了该帖子,该帖子旨在给出答案,但是我不确定如何实施此修复程序(或者说是否在13年后仍然有效)。它确实表明错误消息具有误导性,因为该消息提出的解决方案不起作用。

如果我从Model.Template中删除“设置”访问器并键入Model类(例如,仅通过构造函数进行设置),则该类可以很好地进行序列化-尽管没有Template属性。有没有一种方法可以对未隐藏每个继承类的IXmlSerializable实施XML序列化的类,这些类对a(n)(抽象)基类隐藏属性?

cok*_*n19 5

我看到了david.woodward的这篇文章,展示了一种可行且可行的方法来处理这种情况(即,当不能更改基类时)。它建议提供XmlAttributeOverridesXmlSerializer

使用您提供的对象模型,以下代码说明了此用法。它通过显式告诉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) { }
}
Run Code Online (Sandbox Code Playgroud)