Using DataContractAttribute and ISerializable
I have a set of user defined types which already implement ISerializable interface, now I would like to host them in a server side application and expose few of these types to the client by marking them with DataContract attribute.
Unfortunately,开发者_运维技巧 when I cannot mark the same class with DataContract attribute as it is already ISerializable and it causes runtime exception.
But at the same time, I cannot remove the ISerializable implementation in the old user defined type.
Someone pls help me how do I expose these types to the client.. by marking DataContract and without removing ISerializable
Thanks Sandeep
This is explicitly disallowed -- see http://blogs.msdn.com/b/sowmy/archive/2006/05/14/597476.aspx and http://blogs.msdn.com/b/sowmy/archive/2006/02/22/536747.aspx for clarification.
Because of versioning, one doesn't recognize the other: DataContract knows what ISerializable is, but ISerializable has no clue as to what DataContract is
What about creating a wrapper?
Then sending the wrapper to be serialized/deserialized
[DataContract]
class Person
{
public Person()
{
}
public Person(string firstName, string lastName):this()
{
this.FirstName = firstName;
this.LastName = LastName;
}
[DataMember]
public string FirstName {get;set;}
[DataMember]
public string LastName { get; set; }
}
[Serializable]
class SerializablePersonWrapper : ISerializable
{
SerializablePersonWrapper(SerializationInfo info,
StreamingContext context)
{
string fname = info.GetString("FName");
//did this just for answering any questions
string lname = (string) info.GetValue("LName", typeof(string));
this.PersonItem = new Person(fname, lname);
}
public Person PersonItem {get;set;}
public void GetObjectData(SerializationInfo info,
StreamingContext context)
{
info.AddValue("FName", this.PersonItem.FirstName);
info.AddValue("LName", this.PersonItem.LastName);
}
}
A decade later, and therefore not for the OP, but for anyone else searching this question...
Depending on how you are doing your serialization, you may be able to use SerializationSurrogates. This allows you to choose how to handle serialization at the time you invoke it: if you specify a certain surrogate, it will use that to do the serialization. If you don't specify it, it will use the default.
If we were going to use the sample Mickey Perlstein provided in their answer as a starting point, it might look something like this:
[DataContract]
class Person
{
public Person()
{
}
public Person(string firstName, string lastName):this()
{
this.FirstName = firstName;
this.LastName = LastName;
}
[DataMember]
public string FirstName {get;set;}
[DataMember]
public string LastName { get; set; }
}
class PersonSerializationSurrogate : ISerializationSurrogate
{
public string FirstName { get; set; }
public string LastName { get; set; }
public void GetObjectData(object obj, SerializationInfo info, StreamingContext context)
{
var p = (Person)obj;
info.AddValue(nameof(FirstName), p.FirstName);
info.AddValue(nameof(LastName), p.LastName);
}
public object SetObjectData(object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector)
{
var p = (Person)obj;
p.FirstName = info.GetString(nameof(FirstName));
p.LastName = info.GetString(nameof(LastName));
return p;
}
}
When you need to control the serialization process, as you would have with ISerializable, you can do so with this surrogate. Mostly copying from the linked article:
// This sample uses the BinaryFormatter.
IFormatter formatter = new BinaryFormatter();
// Create a MemoryStream that the object will be serialized into and deserialized from.
using (Stream stream = new MemoryStream())
{
// Create a SurrogateSelector.
var ss = new SurrogateSelector();
// using the Surrogate object.
ss.AddSurrogate(typeof(Person),
new StreamingContext(StreamingContextStates.All),
new PersonSerializationSurrogate());
// Associate the SurrogateSelector with the BinaryFormatter.
formatter.SurrogateSelector = ss;
try
{
// Serialize into the memory stream.
formatter.Serialize(stream, new Person("Jeff", "Sandepku"));
}
catch (SerializationException e)
{
Console.WriteLine($"Serialization failed: {e.Message}");
throw;
}
// Rewind the MemoryStream.
stream.Position = 0;
try
{
// Deserialize from the memory stream.
var p = (Person) formatter.Deserialize(stream);
// Verify that it all worked.
Console.WriteLine($"Name is {p.FirstName} {p.LastName}");
}
catch (SerializationException e)
{
Console.WriteLine($"Deserialization failed: {e.Message}");
throw;
}
}
精彩评论