1

也许标题不是最好的描述。

我的情况是,根据接口,我想编写它的属性之一,即对象。请看下面的例子:

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

我在这里有它的三个实现,检查 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; } }
}

在我的场景中,不使用泛型非常重要。所以有了这个实现,我只需要在 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 属性。

我需要一种方法来编写属性值(而不是存储该接口的所有属性)以及一种知道我正在使用的 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

这是实现它的一种方式,请查看并根据您的需要扩展/重构它。我希望它有所帮助。

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 回答