我有一个应该被序列化和反序列化的类。
但每次服用后,我都需要调用一种同步参考的方法。
无论如何,我可以实现反序列化并使用传统的反序列化,但在常规反序列化后添加对my方法的调用?
答案 0 :(得分:8)
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;
}
}
}
从IXmlDeserializationCallback继承你的类,并在OnXmlDeserialization方法中实现你的同步逻辑。
致How do you find out when you've been loaded via XML Serialization?
<强>更新强>
好吧,据我所知,在每次XML反序列化之后,他都不想“手动”调用某些逻辑。所以不要这样做:
public class MyEntity
{
public string SomeData { get; set; }
public void FixReferences()
{
// call after deserialization
// ...
}
}
foreach (var xmlData in xmlArray)
{
var xmlSer = new XmlSerializer(typeof(MyEntity));
using (var memStream = new MemoryStream(Encoding.UTF8.GetBytes(xmlData)))
{
var entity = (MyEntity)xmlSer.Deserialize(memStream);
entity.FixReferences();
// do something else with the entity
// ...
}
}
他想做反序列化,而不用担心额外的电话。在这种情况下,建议的解决方案是最干净/最简单的 - 您只需要从IXmlDeserializationCallback接口继承您的实体类,并用CustomXmlSerializer替换XmlSerializer:
public class MyEntity: IXmlDeserializationCallback
{
public string SomeData { get; set; }
private void FixReferences()
{
// call after deserialization
// ...
}
public void OnXmlDeserialization(object sender)
{
FixReferences();
}
}
foreach (var xmlData in xmlArray)
{
var xmlSer = new CustomXmlSerializer(typeof(MyEntity));
using (var memStream = new MemoryStream(Encoding.UTF8.GetBytes(xmlData)))
{
var entity = (MyEntity)xmlSer.Deserialize(memStream);
// entity.FixReferences(); - will be called automatically
// do something else with the entity
// ...
}
}
答案 1 :(得分:4)
使用XmlSerializer的选项有限。
如果您可以更改为使用具有优势(和缺点)的DataContractSerializer,那么您可以使用OnDeserializedAttribute。例如
[DataContract]
public class MyClass
{
[DataMember]
public string AMember{get;set;}
[OnDeserialized]
public void OnDeserialized(StreamingContext context)
{
// called after deserializing instance of MyClass
}
}
答案 2 :(得分:1)
我有一个很好的解决方案4你
写下这个静态类
public delegate void OnDeserializedEventArgs(object itemDeserialized, string xmlSource);
public delegate void OnDeserializedFailedEventArgs(string xmlSource);
public static class SerializationServices
{
public static event OnDeserializedEventArgs OnDeserializedEvent;
public static event OnDeserializedFailedEventArgs OnDeserializedFailedEvent;
public static T Deserialize<T>(this string item) where T : class
{
XmlSerializer ser = new XmlSerializer(item.GetType());
StringReader sr = new StringReader(item);
var obj = ser.Deserialize(sr);
if (obj is T)
{
if (OnDeserializedEvent != null)
OnDeserializedEvent(obj, item);
return obj as T;
}
if (OnDeserializedFailedEvent != null)
OnDeserializedFailedEvent(item);
//callback - invalid event
return null;
}
}
然后将其与此代码一起使用
public class MyDesrializedClass
{
//put some properties here...
}
class Program
{
static void Main(string[] args)
{
SerializationServices.OnDeserializedEvent += SerializationServices_OnDeserializedEvent;
SerializationServices.OnDeserializedFailedEvent += SerializationServices_OnDeserializedFailedEvent;
string someXml = string.Empty; //replace this with something...
MyDesrializedClass deserializedClass = someXml.Deserialize<MyDesrializedClass>();
}
private static void SerializationServices_OnDeserializedFailedEvent(string xmlSource)
{
//will get here before 'deserializedClass' will get it's results
}
private static void SerializationServices_OnDeserializedEvent(object itemDeserialized, string xmlSource)
{
//will get here before 'deserializedClass' will get it's results
}
}
如果你将这些代码粘贴到不同的命名空间中,请不要忘记添加'using ...'otherwize你不会在程序上下文中看到反序列化的方法
Tzahi