我正在尝试通过XML序列化加载对象树,此刻它将加载对象,并非常愉快地创建树。我的问题围绕着以下事实:这些类支持一定程度的审核。我想做的是在每个对象加载完成后在每个对象上调用一些方法。
为了便于讨论,假设我有一个相当通用的对象树,在不同级别上具有不同的类,例如:
<Customer name="Foo Bar Inc."> <Office IsHq="True"> <Street>123 Any Street</Street> <Town name="Anytown"> <State name="Anystate"> <Country name="My Country" /> </State> </Town> </Office> <Office IsHq="False"> <Street>456 High Street</Street> <Town name="Anycity"> <State name="Anystate"> <Country name="My Country" /> </State> </Town> </Office> </Customer>
有什么方法可以使用默认的序列化程序(类似于您可以创建类似方法ShouldSerializeFoo)来确定何时为每个对象完成加载?
ShouldSerializeFoo
编辑: 我应该指出,在反序列化之后暴露类似于OnLoaded()我 可以 调用的方法的显而易见的情况令我感到“不好做”。
OnLoaded()
Edit2: 为了便于讨论,这是我当前的 hack “方法”,适用于基本级别,但是子City节点仍然认为它需要进行更改保存(在现实世界中,对象模型要复杂得多) ,但这至少可以编译,而无需完整的源代码)
public class Office { [XmlAttribute("IsHq")] public bool IsHeadquarters { get; set; } [XmlElement] public string Street { get; set; } [XmlElement] public Town Town { get; set; } protected virtual void OnLoaded() {} public static OfficeCollection Search() { OfficeCollection retval = new OfficeCollection(); string xmlString = @" <Office IsHq='True'> <Street>123 Any Street</Street> <Town name='Anytown'> <State name='Anystate'> <Country name='My Country' /> </State> </Town> </Office>"; XmlSerializer xs = new XmlSerializer(retval.GetType()); XmlReader xr = new XmlTextReader(xmlString); retval = (OfficeCollection)xs.Deserialize(xr); foreach (Office thisOffice in retval) { thisOffice.OnLoaded(); } return retval; } }
嗯…还不是很漂亮,但是您可以将反序列化逻辑重构为一个专用的类,该类可以在将其返回给调用者之前通知反序列化对象它源自XML。
更新: 我认为这应该很容易做到,而不会偏离框架设置的模式太多……您只需要确保使用CustomXmlSerializer即可。需要此通知的类仅需要实现IXmlDeserializationCallback
using System.Xml.Serialization; namespace Custom.Xml.Serialization { public interface IXmlDeserializationCallback { void OnXmlDeserialization(object sender); } public class CustomXmlSerializer : XmlSerializer { protected override object Deserialize(XmlSerializationReader reader) { var result = base.Deserialize(reader); var deserializedCallback = result as IXmlDeserializationCallback; if (deserializedCallback != null) { deserializedCallback.OnXmlDeserialization(this); } return result; } } }