也许标题不是最好的描述。
我的情况是,根据一个接口,我想写一个属于object的属性。请观看以下示例:
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中写入属性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属性。
我需要一种方法来编写属性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编写的,这次我看不到它们。如何恢复我的物体?
答案 0 :(得分: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());
}
}