2012-05-02 10 views
1

多分タイトルが最も良い説明ではありません。派生クラスを使用してXMLに書き込む方法は?

私の状況は、インタフェースによってはオブジェクトのプロパティの1つを書きたいと思っています。値がtrueのデータ型が隠されていることができることを確認し、

public interface IFoo 
{ 
    // anothers properties... 
    object Value { get; } 
} 

をそして私はここでの3つの実装を持って次の例を見てください。

public class FooA : IFoo 
{ 
    public string Value { get; set; } 
    object IFoo.Value { get { return Value; } } 
} 

public class FooB : IFoo 
{ 
    public int Value { get; set; } 
    object IFoo.Value { get { return Value; } } 
} 

public class FooC : IFoo 
{ 
    public List<double> Value { get; set; } 
    object IFoo.Value { get { return Value; } } 
} 

私のシナリオでは、ジェネリックを使用しないことが非常に重要でした。ですから、この実装では、XmlのプロパティValueだけを記述する必要があります。例えば

static void Main(string[] args) 
    { 
     List<IFoo> fooList = new List<IFoo>() 
     { 
      new FooA() { Value = "String" }, 
      new FooB() { Value = 2 }, 
      new FooC() { Value = new List<double>() {2, 3.4 } } 
     }; 

     // Write in a Xml the elements of this list with the property Value (and the problem is the datartype, 
     // strings, ints, lists, etc) 
     // ... 
    } 

私はXmlSerializationを使用して考えていたが、私は、オブジェクトのすべてのプロパティ、ちょうどValueプロパティを保存する必要はありません。

プロパティ(そのインターフェイスのすべてのプロパティを格納しない)プロパティと、使用しているIFooの実装を知る方法を記述する方法が必要です。

更新:このようなXMLファイルが必要です。

<Foos> 
    <Foo xsi:Type="FooA" Value="String" /> 
    <Foo xsi:Type="FooB" Value="2" /> 
    <Foo xsi:Type="FooC" > 
     <Value> 
      <List xsi:Type="Double"> 
       <Element>2</Element> 
       <Element>3.4</Element> 
      </List> 
     </Value> 
    </Foo 
</Foos> 

これは単なるアイデアです。アイデアは、IFooのプロパティとその値を持つ具体的なオブジェクトを取得する機能を格納することです。

UPDATE:アイデアで私を助けるためにラジNagalingamへ

感謝。これが私が達成したことです。

public interface IFoo 
{ 
    object Value { get; } 
} 

public abstract class Foo<T> : IFoo, IXmlSerializable 
{ 
    [XmlElement] 
    public T Value { get; set; } 
    [XmlIgnore] 
    object IFoo.Value { get { return Value; } } 

    XmlSchema IXmlSerializable.GetSchema() { return null; } 
    void IXmlSerializable.ReadXml(XmlReader reader) { throw new NotImplementedException(); } 
    void IXmlSerializable.WriteXml(XmlWriter writer) 
    { 
     XmlSerializer serial = new XmlSerializer(Value.GetType()); 
     serial.Serialize(writer, Value); 
    } 
} 

public class FooA : Foo<string> { } 
public class FooB : Foo<int> { } 
public class FooC : Foo<List<Double>> { } 
public class FooContainer : List<IFoo>, IXmlSerializable 
{ 
    public XmlSchema GetSchema() { return null; } 
    public void ReadXml(XmlReader reader) { throw new NotImplementedException(); } 
    public void WriteXml(XmlWriter writer) 
    { 
     ForEach(x => 
      { 
       XmlSerializer serial = new XmlSerializer(x.GetType()); 
       serial.Serialize(writer, x); 
      }); 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     FooContainer fooList = new FooContainer() 
     { 
      new FooA() { Value = "String" }, 
      new FooB() { Value = 2 }, 
      new FooC() { Value = new List<double>() {2, 3.4 } } 
     }; 

     XmlSerializer serializer = new XmlSerializer(fooList.GetType(), 
      new Type[] { typeof(FooA), typeof(FooB), typeof(FooC) }); 
     System.IO.TextWriter textWriter = new System.IO.StreamWriter(@"C:\temp\demo.xml"); 
     serializer.Serialize(textWriter, fooList); 
     textWriter.Close(); 
    } 
} 

そして、それは動作しますが、私はそれが私はそれがXSIを使って書かれていることがわかり、標準のシリアル化を使用して、具体的なクラスでリストを回復することは不可能だと思うし、今回は私がそれらを見ることができません。オブジェクトを復元するにはどうしたらいいですか?

答えて

1

これを実装する方法の1つです。必要に応じてplsを拡張/リファクタリングしてください。私はそれが助けて欲しい

public interface IFoo : IXmlSerializable 
{ 
    // anothers properties... 
    object Value { get; } 
} 

[XmlRoot("Foo")] 
public class FooA : IFoo 
{ 
    public string Value { get; set; } 
    object IFoo.Value { get { return Value; } } 

    #region IXmlSerializable Members 

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

    public void ReadXml(XmlReader reader) 
    { 
    } 

    public void WriteXml(XmlWriter writer) 
    { 
     writer.WriteStartElement("Foo"); 

     writer.WriteStartAttribute("Type", "http://example.com/2007/ns1"); 
     writer.WriteString(GetType().Name); 
     writer.WriteEndAttribute(); 

     writer.WriteStartAttribute("Value"); 
     writer.WriteString(Value.ToString()); 
     writer.WriteEndAttribute(); 

     writer.WriteEndElement(); 

    } 

    #endregion 
} 

[XmlRoot("Foo")] 
public class FooB : IFoo 
{ 
    public int Value { get; set; } 
    object IFoo.Value { get { return Value; } } 

    #region IXmlSerializable Members 

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

    public void ReadXml(XmlReader reader) 
    { 
    } 

    public void WriteXml(XmlWriter writer) 
    { 
     writer.WriteStartElement("Foo"); 

     writer.WriteStartAttribute("Type", "http://example.com/2007/ns1"); 
     writer.WriteString(GetType().Name); 
     writer.WriteEndAttribute(); 

     writer.WriteStartAttribute("Value"); 
     writer.WriteString(Value.ToString()); 
     writer.WriteEndAttribute(); 

     writer.WriteEndElement(); 
    } 

    #endregion 
} 

[XmlRoot("Foo")] 
public class FooC : IFoo 
{ 
    public List<double> Value { get; set; } 
    object IFoo.Value { get { return Value; } } 

    #region IXmlSerializable Members 

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

    public void ReadXml(XmlReader reader) 
    { 
    } 

    public void WriteXml(XmlWriter writer) 
    { 
     writer.WriteStartElement("Foo"); 

     writer.WriteStartAttribute("Type", "http://example.com/2007/ns1"); 
     writer.WriteString(GetType().Name); 
     writer.WriteEndAttribute(); 

     writer.WriteStartElement("Value"); 

     if (Value != null) 
     { 
      writer.WriteStartElement("List"); 

      writer.WriteStartAttribute("Type", "http://example.com/2007/ns1"); 
      writer.WriteString(typeof(double).Name); 
      writer.WriteEndAttribute(); 

      foreach (double value in Value) 
      { 
       writer.WriteElementString("Element", value.ToString()); 
      } 

      writer.WriteEndElement(); 

     } 

     writer.WriteEndElement(); 

     writer.WriteEndElement(); 
    } 

    #endregion 
} 

[XmlRoot("Foos")] 
public class ListCotainer : List<IFoo>, IXmlSerializable 
{ 
    #region IXmlSerializable Members 

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

    public void ReadXml(XmlReader reader) 
    { 
    } 

    public void WriteXml(XmlWriter writer) 
    { 
     writer.WriteAttributeString("xmlns", "xsi", null, "http://example.com/2007/ns1"); 
     foreach (IFoo foo in this) 
     { 
      foo.WriteXml(writer); 
     } 
    } 

    #endregion 
} 
class Program 
{ 
    static void Main(string[] args) 
    { 
     XmlWriterSettings _xws = new XmlWriterSettings(); 
     _xws.OmitXmlDeclaration = true; 
     _xws.ConformanceLevel = ConformanceLevel.Auto; 
     _xws.Indent = true; 

     ListCotainer container = new ListCotainer() 
     { 
       new FooA() { Value = "String" }, 
       new FooB() { Value = 2 }, 
       new FooC() { Value = new List<double>() {2, 3.4 } } 
     }; 

     StringBuilder xmlString = new StringBuilder(); 
     using (XmlWriter xtw = XmlTextWriter.Create(xmlString, _xws)) 
     { 
      XmlSerializer serializer = new XmlSerializer(container.GetType()); 
      serializer.Serialize(xtw, container); 

      xtw.Flush(); 
     } 
     Console.WriteLine(xmlString.ToString()); 
    } 
} 
+0

解決方法は問題ありません。私はFooのようなモジュールを100個作成する予定です。そのため多くのモジュールに繰り返しデータ型を含めることができます。これを行う唯一の方法だと思いますか?私が実装する各モジュロはIXmlSerialization –

+0

を持つ必要があります。これは、クラスのXMLシリアル化を必要な方法でカスタマイズする唯一の方法です。 XML出力について気にしない場合は、.NETが提供する標準的なシリアライゼーションを使用することもできます。 – RajN

+0

Valueプロパティで[XmlElement]などの標準シリアル化を使用することは可能でしょうか。私はインターフェイスをシリアル化しようとしていたので問題が発生しました –

関連する問題