是否可以将自定义结构序列化为xml属性?
示例代码:
public class Dummy<T>
{
private Dummy() { }
public Dummy(T item1)
{
Item1 = item1;
Item2 = item1;
}
public T Item1 { get; set; }
[XmlAttribute]
public T Item2 { get; set; }
}
public struct Meh
{
public int Prop { get; set; }
}
[Test]
public void XmlMehTest()
{
var meh = new Meh{Prop = 1};
var dummy = new Dummy<Meh>(meh);
using (var writer = new StringWriter())
{
var serializer = new XmlSerializer(dummy.GetType());
// System.InvalidOperationException : Cannot serialize member 'Meh2' of type Meh.
// XmlAttribute/XmlText cannot be used to encode complex types.
serializer.Serialize(writer, dummy);
Console.Write(writer.ToString());
}
}
[Test]
public void XmlDateTimeTest()
{
var dummy = new Dummy<DateTime>(DateTime.Now);
using (var writer = new StringWriter())
{
var serializer = new XmlSerializer(dummy.GetType());
serializer.Serialize(writer, dummy);
Console.Write(writer.ToString());
}
}
请忽略结构是可变的,就像紧凑的样本那样写。
这确实是first-world-developer-problem,但我仍然很好奇:)
答案 0 :(得分:3)
您只能将XmlAttributeAttribute分配给返回值(或值数组)的公共字段或公共属性,可以映射到XML Schema定义语言(XSD)之一简单类型(包括从XSD anySimpleType类型派生的所有内置数据类型)。可能的类型包括可以映射到XSD简单类型的任何类型,包括Guid,Char和枚举。
所以要做到这一点,我们应该能够为XSD创建自己的类型定义,我想我们可以做到这一点。因为这个documentation包含了对它的完整解释。但是我们不能做的是,我们不能将我们的定义包含在this列表中。最初XML Serializer使用这些类型来确定类型的XSD类型定义。您可以将此属性与DateTime
一起使用,因为它使用此方法创建定义并存储在HashTable中:
AddPrimitive(typeof(DateTime), "dateTime", "DateTime",
TypeFlags.XmlEncodingNotRequired |
TypeFlags.HasCustomFormatter |
TypeFlags.CanBeElementValue | **TypeFlags.CanBeAttributeValue**);
AddPrimitive
方法:
private static void AddPrimitive(Type type, string dataTypeName, string formatterName, TypeFlags flags)
{
XmlSchemaSimpleType dataType = new XmlSchemaSimpleType {
Name = dataTypeName
};
TypeDesc desc = new TypeDesc(type, true, dataType, formatterName, flags);
if (primitiveTypes[type] == null)
{
primitiveTypes.Add(type, desc);
}
primitiveDataTypes.Add(dataType, desc);
primitiveNames.Add(dataTypeName, "http://www.w3.org/2001/XMLSchema", desc);
}
这个定义从XmlReflectionImporter
这样调用(根据StackTrace生成异常):
this.GetTypeDesc(name, ns, TypeFlags.CanBeElementValue | TypeFlags.CanBeTextValue | TypeFlags.CanBeAttributeValue);
我想最重要的是TypeFlags.CanBeAttributeValue
,我认为它指定此类型可以是非常值。因此,我们可以将自定义结构序列化为XmlAttirube
,但我们不能使用标准XmlSerializer
来做。因为我说它使用this列表来计算XSD类型定义。它是一个初始列表,并且不可能在该列表中添加新元素。
P.S。您可能需要查看http://msdn.microsoft.com/en-us/library/8w07bk3h(v=vs.80).aspx