以下是我正在努力完成的一个简化示例。
我有一个类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构造函数中。 我创建了它:(用初始构造)
I serialized it: ( constructed with initial )
Json:
{"SerializeMeThroughISerializable":{"WhyAmIHere":"( constructed with initial )"}}
I deserialized it: ( constructed with initial )
显然,如果DoNotSerializeMe真的不可序列化,这会导致错误。
有没有一种优雅的方法可以在不使用Json.NET的情况下解决这个问题?我不确定为什么mono的行为与.NET的行为不同。
答案 0 :(得分:0)
我将建议一种替代方法:使用代理数据传输类型来序列化您的[MonoTODO]
类。一种方法是使用Data Contract Surrogates。但单声道是否支持数据合同代理? current version of the source code表明它们是,但this version将其显示为SerializeMe
,因此我无法保证您的单声道版本具有DataContractJsonSerializer.DataContractSurrogate
的有效实施。
但是,手动代理属性始终有效。例如,即使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
更简单,因为CannotBeSerializedDirectly
以外的所有成员都会继续自动序列化。请注意[IgnoreDataMember]
的使用。它阻止[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; }
}
成员包含在类的隐式数据协定中。
如果您希望您的代理是私有的,或者需要控制代理成员名称,您需要为包含类型提供明确的数据合同:
<div class="b <%= id %>"></div>