sch*_*her 1 c# xml generics xml-serialization
我想为泛型类创建一个xml.其中一个属性具有泛型类型.对于此属性,我不希望将属性名称用作其XML元素名称,而是使用泛型类型的名称.
这个类看起来像这样:
[XmlRoot("Entity")]
public class StoreItem<TEntity>
where TEntity : class, new()
{
/// <summary>
/// Gets and sets the status of the entity when storing.
/// </summary>
[XmlAttribute]
public System.Data.Services.Client.EntityStates Status { get; set; }
/// <summary>
/// Gets and sets the entity to be stored.
/// </summary>
public TEntity Entity { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
在序列化某种商店项目时StoreItem<SewageArea>,XML应包含以下内容:
<Entity Status="Deleted">
<SewageArea ...>
...
</SewageArea>
<Entity>
Run Code Online (Sandbox Code Playgroud)
要求是,SewageArea上面的例子应该以"正常"方式序列化.另一个重要的事情是,如果可能的话,代码应该准备好在类中自动序列化新添加的属性StoreItem.
在序列化为XML时,您希望沿着Rename类的行执行某些操作,但是您不能因为属性参数不能包含泛型类型参数,即[XmlElement(typeof(TEntity))].而实施的明显替代方案IXmlSerializable是不方便的,因为您丢失了随后添加到的属性的自动序列化StoreItem<TEntity>.
相反,你可以做的是让使用的[XmlAnyElement]替代性质做了嵌套的系列化你的TEntity,如下:
[XmlRoot("Entity")]
public class StoreItem<TEntity>
where TEntity : class, new()
{
/// <summary>
/// Gets and sets the status of the entity when storing.
/// </summary>
[XmlAttribute]
public System.Data.Services.Client.EntityStates Status { get; set; }
/// <summary>
/// Gets and sets the entity to be stored.
/// </summary>
[XmlIgnore]
public TEntity Entity { get; set; }
[XmlAnyElement]
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never), DebuggerBrowsable(DebuggerBrowsableState.Never)]
public XElement XmlEntity
{
get
{
return (Entity == null ? null : XObjectExtensions.SerializeToXElement(Entity, null, true));
}
set
{
Entity = (value == null ? null : XObjectExtensions.Deserialize<TEntity>(value));
}
}
}
Run Code Online (Sandbox Code Playgroud)
使用扩展方法:
public static class XObjectExtensions
{
public static T Deserialize<T>(this XContainer element)
{
return element.Deserialize<T>(null);
}
public static T Deserialize<T>(this XContainer element, XmlSerializer serializer)
{
using (var reader = element.CreateReader())
{
serializer = serializer ?? new XmlSerializer(typeof(T));
object result = serializer.Deserialize(reader);
if (result is T)
return (T)result;
}
return default(T);
}
public static XElement SerializeToXElement<T>(this T obj)
{
return obj.SerializeToXElement(null, true);
}
public static XElement SerializeToXElement<T>(this T obj, XmlSerializer serializer, bool omitStandardNamespaces)
{
var doc = new XDocument();
using (var writer = doc.CreateWriter())
{
XmlSerializerNamespaces ns = null;
if (omitStandardNamespaces)
(ns = new XmlSerializerNamespaces()).Add("", ""); // Disable the xmlns:xsi and xmlns:xsd lines.
serializer = serializer ?? new XmlSerializer(obj.GetType());
serializer.Serialize(writer, obj, ns);
}
var element = doc.Root;
if (element != null)
element.Remove();
return element;
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,[XmlAnyElement]将为所有未知元素调用该属性,因此如果您的XML由于某种原因具有意外元素,则可能会XObjectExtensions.Deserialize<TEntity>(value))因为根元素名称错误而引发异常.如果可能,您可能希望捕获并忽略此方法的异常.
然后,为样本TEntity类
public class SewageArea
{
public double Area { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
XML输出是:
Run Code Online (Sandbox Code Playgroud)<Entity Status="State1"> <SewageArea> <Area>10101</Area> </SewageArea> </Entity>
样品小提琴.
| 归档时间: |
|
| 查看次数: |
1435 次 |
| 最近记录: |