1

多分タイトルは最良の説明ではありません。

私の状況は、インターフェイスに応じて、オブジェクトであるそのプロパティの1つを書きたいということです。次の例を見てください。

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

ここには 3 つの実装があります。Value が真のデータ型を非表示にできることを確認してください。

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; } }
}

私のシナリオでは、ジェネリックを使用しないことが非常に重要でした。したがって、この実装では、プロパティ Value だけを Xml に書き込む必要があります。

例えば:

    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 プロパティだけを保存したいと考えています。

プロパティ 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 のプロパティと、値を持つ具体的なオブジェクトを取得する機能だけを格納することです。

アップデート:

アイデアを手伝ってくれた Raj 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を使用して記述されていることがわかり、今回はそれらを見ることができません. オブジェクトを復元するにはどうすればよいですか?

4

1 に答える 1

1

これを実装する方法の 1 つを次に示します。ご覧になり、必要に応じて拡張/リファクタリングしてください。お役に立てば幸いです。

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());
    }
}
于 2012-05-02T18:13:16.360 に答える