I have a class which should be serialized and deserialzed.
But every time after deserilization I need to call a method of synchronizing references.
Anyway I can implement the deserialization and use the traditional deserialization but add the call to my method after the regular deserialization?
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;
}
}
}
inherit your class from IXmlDeserializationCallback and implement your synchronizing logic in OnXmlDeserialization method.
credits to How do you find out when you've been loaded via XML Serialization?
UPDATE:
well, as far as I understand the topicstarter, he does not want to "manually" call some logic after each XML deserialization. So instead of doing this:
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
// ...
}
}
he wants to do just deserialization, without worrying about extra calls. In this case, proposed solution is the cleanest / simplest - you only need to inherit your entity class from IXmlDeserializationCallback interface, and replace XmlSerializer with CustomXmlSerializer:
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
// ...
}
}
i have a nice solution 4 u
write this static class
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;
}
}
and then use it with this code
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
}
}
if u paste these code into diferent namespaces don't forget to add the 'using ...' otherwize u wont see the method deserialize in the program context
Tzahi
Your options using XmlSerializer are limited.
If you can change to using the DataContractSerializer, which has its advantanges (and disadvantages) then you can use the OnDeserializedAttribute. For example
[DataContract]
public class MyClass
{
[DataMember]
public string AMember{get;set;}
[OnDeserialized]
public void OnDeserialized(StreamingContext context)
{
// called after deserializing instance of MyClass
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With