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です。また、-methodを追加するまでには至っていませんが、WriteXmlここではかなり簡単なはずです...

于 2012-09-17T14:15:55.853 に答える