1

是否有一种本地方式来映射以下 xml...

<Tag type="1" />
<Tag type="2" />

...基于“type”属性的值,具体类“Type1Tag”和“Type2Tag”(均派生自抽象类Tag)?

(类似于 NHibernate 的鉴别器: DiscriminateSubClassesOnColumn(...)/DiscriminatorValue(...) )

我不是在寻找类似XmlSerializer + Polymorphism中报告的映射,它通过标记名称而不是属性值来区分类型(我无法更改 xml 结构):)

4

1 回答 1

3

我可能在您的实施中为时已晚,无法提供任何帮助,但这是我本周末想出的,并认为我会分享给其他人,因为它似乎满足了我的需求。

请注意这里没有错误处理,您可以根据需要创建自己的子对象类型初始化。

我有许多不同的类,它们都是相同类型的元素,但可以根据属性的值保存不同的内容。

我使用了IXmlSerializable-interface并实现了读取每个类型标签的方法...

Xml 输入:

<Parent>
  <Tag type="1"/>
  <Tag type="2"/>
</Parent>

父类是什么实现IXmlSerializable

public class Parent : IXmlSerializable
{
    [XmlElement("Tag")]
    public List<TagBase> Tags { get; set; }

    #region IXmlSerializable Members

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

    public void ReadXml(System.Xml.XmlReader reader)
    {
       // this line causes the root Parent node to be ignored, and gets to the children Tag elements
       reader.Read();

       while (reader.ReadToNextSibling("Tag"))
       {
           string attributeType = reader.GetAttribute("type");

           Type type = null;

           switch(attributeType)
           {
              case "1":
                  type = typeof(Type1Tag);
                  break;
              case "2":
                  type = typeof(Type2Tag);
                  break;
              default:
                  continue;
           }

           XmlSerializer serializer = new XmlSerializer(type);

           // this line is the key to rejoining the automatic xml deserialization of all
           // the child stuff
           TagBase tagBase = (TagBase)serializer.Deserialize(reader.ReadSubtree());

           this.Tags.Add(tagBase);
        }
    }

    public void WriteXml(System.Xml.XmlWriter writer)
    {
        throw new NotImplementedException();
    }

    #endregion IXmlSerializable Members
}

我创建了一个抽象TagBase类,每个标签类型都会继承:

[XmlRoot("Tag")]
public abstract class TagBase
{
   [XmlAttribute("type")]
   public string Type { get; set; }
}

然后,可以使用您的自定义属性等正常实现每个其他类...

[XmlRoot("Tag")]
public class Type1Tag : TagBase
{
    // your implementation
}

[XmlRoot("Tag")]
public class Type2Tag : TagBase
{
    // your implementation
}

请注意,我XmlRootAttribute在这里使用并包含它们,因为我有一堆命名空间在尝试反序列化子标签时导致异常,但是 YMMV. 我还没有达到添加 - 方法的地步WriteXml,但在这里应该很简单......

于 2012-09-17T14:15:55.853 回答