![](/img/trans.png)
[英]ISerializable.GetObjectData(SerializationInfo, StreamingContext)
[英]DataContractJsonSerializer ; ISerializable GetObjectData called with .NET but not with mono
以下是我要完成的工作的简化示例。
我有一个类DoNotSerializeMe,它是外部库的一部分,不能序列化。
using System;
namespace CustomJsonSerialization
{
public class DoNotSerializeMe
{
public string WhyAmIHere;
public DoNotSerializeMe(string mystring)
{
Console.WriteLine(" In DoNotSerializeMe constructor.");
WhyAmIHere = "( constructed with " + mystring + " )";
}
}
}
我也有一个SerializeMe类,该类具有DoNotSerializeMe类型的成员。 我可以使此类实现ISerializable,并通过提取数据和调用构造函数来解决DoNotSerializeMe无法序列化的问题。
using System.Runtime.Serialization;
using System.Security.Permissions;
namespace CustomJsonSerialization
{
[System.Serializable]
public class SerializeMe : ISerializable
{
public DoNotSerializeMe SerializeMeThroughISerializable;
public SerializeMe(string mystring)
{
SerializeMeThroughISerializable = new DoNotSerializeMe(mystring);
}
protected SerializeMe(SerializationInfo info, StreamingContext context)
{
System.Console.WriteLine(" In SerializeMe constructor (ISerializable)");
SerializeMeThroughISerializable = new DoNotSerializeMe(info.GetString("SerializeMeThroughISerializable"));
}
[SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
{
System.Console.WriteLine(" In SerializeMe.GetObjectData()");
info.AddValue("SerializeMeThroughISerializable",
"( deserialized through getObjectData " +
SerializeMeThroughISerializable.WhyAmIHere + " )");
}
}
}
下面是一个序列化和反序列化对象的简短程序:
using System;
using System.IO;
using System.Runtime.Serialization.Json;
using System.Text;
namespace CustomJsonSerialization
{
public class Program
{
public static void Main(string[] args)
{
SerializeMe serializeme = new SerializeMe("initial");
Console.WriteLine("I created it: {0}", serializeme.SerializeMeThroughISerializable.WhyAmIHere);
Console.WriteLine();
MemoryStream memstream = new MemoryStream();
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(SerializeMe));
serializer.WriteObject(memstream, serializeme);
Console.WriteLine("I serialized it: {0}", serializeme.SerializeMeThroughISerializable.WhyAmIHere);
Console.WriteLine();
Console.WriteLine("Json:");
Console.WriteLine(Encoding.ASCII.GetString(memstream.ToArray()));
Console.WriteLine();
memstream.Seek(0, SeekOrigin.Begin);
SerializeMe anotherSerializeMe = (SerializeMe)serializer.ReadObject(memstream);
Console.WriteLine("I deserialized it: {0}", anotherSerializeMe.SerializeMeThroughISerializable.WhyAmIHere);
}
}
}
通过.NET(4.5)运行时,得到以下信息:
In DoNotSerializeMe constructor.
I created it: ( constructed with initial )
In SerializeMe.GetObjectData()
I serialized it: ( constructed with initial )
Json:
{"SerializeMeThroughISerializable":"( deserialized through getObjectData ( constructed with initial ) )"}
In SerializeMe constructor (ISerializable)
In DoNotSerializeMe constructor.
I deserialized it: ( constructed with ( deserialized through getObjectData ( constructed with initial ) ) )
当进行序列化/反序列化时(如预期的那样),序列化程序调用了ISerializable结构和GetObjectData。 我从不直接序列化或反序列化DoNotSerializeMe对象。
但是,当通过mono运行相同的构建时(尝试过3.10.0和4.0.2),我得到以下信息:在DoNotSerializeMe构造函数中。 我创建了它:(用initial构造)
I serialized it: ( constructed with initial )
Json:
{"SerializeMeThroughISerializable":{"WhyAmIHere":"( constructed with initial )"}}
I deserialized it: ( constructed with initial )
显然,如果DoNotSerializeMe确实不可序列化,则将导致错误。
有没有不用Json.NET就能解决此问题的优雅方法? 我不确定为什么单声道与.NET的行为方式不同。
我将建议一种替代方法:使用替代数据传输类型来序列化您的DoNotSerializeMe
类。 一种方法是使用Data Contract Surrogates 。 但是单声道支持数据合同替代吗? 当前版本的源代码表明它们是,但是此版本将其显示为[MonoTODO]
,因此我不能保证您的mono版本具有DataContractJsonSerializer.DataContractSurrogate
的有效实现。
但是,手动代理属性将始终起作用。 例如,即使不能直接序列化以下SerializeMe
类型的DoNotSerializeMe
成员,也可以对其进行序列化和序列化:
public class DoNotSerializeMe
{
public readonly string WhyAmIHere;
readonly bool ProperlyConstructed; // data contract serializer does not call the constructor
public DoNotSerializeMe(string mystring)
{
Console.WriteLine(string.Format(" In DoNotSerializeMe constructor, mystring = \"{0}\"", mystring));
WhyAmIHere = mystring;
ProperlyConstructed = true;
}
public void Validate()
{
if (!ProperlyConstructed)
throw new InvalidOperationException("!ProperlyConstructed");
}
}
public class SerializeMe
{
[IgnoreDataMember]
public DoNotSerializeMe CannotBeSerializedDirectly;
public DoNotSerializeMeSurrogate DoNotSerializeMeSurrogate
{
get
{
if (CannotBeSerializedDirectly == null)
return null;
return new DoNotSerializeMeSurrogate { WhyAmIHereSurrogate = CannotBeSerializedDirectly.WhyAmIHere };
}
set
{
if (value == null)
CannotBeSerializedDirectly = null;
else
CannotBeSerializedDirectly = new DoNotSerializeMe(value.WhyAmIHereSurrogate);
}
}
public string SomeOtherField { get; set; }
}
public class DoNotSerializeMeSurrogate
{
public string WhyAmIHereSurrogate { get; set; }
}
使用此方法看起来比实现ISerializable
更简单,因为除CannotBeSerializedDirectly
以外的所有成员都将继续自动进行序列化。 注意[IgnoreDataMember]
的使用。 这样可以防止CannotBeSerializedDirectly
成员包含在该类的隐式数据协定中。
如果您希望自己的代理人是私有的,或者需要控制代理人的成员名,则需要为包含类型赋予显式数据协定:
[DataContract]
public class SerializeMe
{
[IgnoreDataMember]
public DoNotSerializeMe CannotBeSerializedDirectly;
[DataMember]
DoNotSerializeMeSurrogate DoNotSerializeMeSurrogate
{
get
{
if (CannotBeSerializedDirectly == null)
return null;
return new DoNotSerializeMeSurrogate { WhyAmIHereSurrogate = CannotBeSerializedDirectly.WhyAmIHere };
}
set
{
if (value == null)
CannotBeSerializedDirectly = null;
else
CannotBeSerializedDirectly = new DoNotSerializeMe(value.WhyAmIHereSurrogate);
}
}
[DataMember]
public string SomeOtherField { get; set; }
}
[DataContract]
class DoNotSerializeMeSurrogate
{
[DataMember]
public string WhyAmIHereSurrogate { get; set; }
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.