【发布时间】:2013-12-17 18:48:25
【问题描述】:
作为这个问题JSON.NET CustomCreationConverter with nested objects 的部分问题,我尝试在反序列化期间调用自定义构造函数。我简化的类层次结构如下:
public abstract class BusinessObjectBase
{
internal BusinessObjectBase(SerializationContext context)
: base(context)
{
}
}
public abstract class EditableObjectBase : BusinessObjectBase
{
protected EditableObjectBase(SerializationContext context)
: base(context)
{
}
}
public class EditableObjectCollection<TObject> : BusinessObjectBase, ICollection<TObject>, IList, INotifyCollectionChanged where TObject : BusinessObjectBase
{
protected EditableObjectCollection(SerializationContext context)
: base(context)
{
}
}
我知道对象层次结构到一定程度,但允许/强制用户派生自己的类。我的想法是编写一个自定义创建转换器。我要解决的问题是序列化对象中的属性可以声明为抽象的 BusinessObjectBase,但真正的对象将是一个更派生的类,并且可能是一个集合或不是一个集合。 CustomCreationConverter 只能将这个抽象类型传递给 Create 方法,当然不能从这个信息中创建正确的类型。
受How to implement custom JsonConverter in JSON.NET to deserialize a List of base class objects的启发,我实现了一个转换器,如下所示:
internal class BusinessObjectCreationConverter : JsonConverter
{
public override bool CanWrite
{
get
{
return false;
}
}
public override bool CanConvert(Type objectType)
{
return typeof(BusinessObjectBase).IsAssignableFrom(objectType);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
object result = null;
if (reader.TokenType != JsonToken.Null)
{
JObject jsonObject = JObject.Load(reader);
result = this.Create(objectType, jsonObject);
Verification.Assert<NullReferenceException>(result != null, "No Business Object created.");
serializer.Populate(jsonObject.CreateReader(), result);
}
return result;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
}
public BusinessObjectBase Create(Type objectType, JObject jsonObject)
{
JToken token = jsonObject.SelectToken("$type");
var typeString = token.Value<string>();
Type type = Type.GetType(typeString);
var businessObject = type.CreateUsingDesrializationConstructor<BusinessObjectBase>();
businessObject.Initialize(true);
return businessObject;
}
}
我测试序列化的类如下所示:
public class AnyPocoContainingBusinessObject
{
public BusinessObjectBase BusinessObject { get; set; }
}
public class TestEditableObject : EditableObjectBase
{
internal TestEditableObject(SerializationContext context)
: base(context)
{
}
}
如果我用一个集合初始化我的班级我的班级
var collection = new EditableObjectCollection<TestEditableObject>(null);
var poco = new AnyPocoContainingBusinessObject { BusinessObject = collection };
并以这种方式配置序列化程序:
public NewtonsoftJsonSerializer()
: this(new JsonSerializer
{
TypeNameHandling = TypeNameHandling.Auto,
ObjectCreationHandling = ObjectCreationHandling.Replace,
PreserveReferencesHandling = PreserveReferencesHandling.Objects,
ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor,
DefaultValueHandling = DefaultValueHandling.Ignore,
ContractResolver = new KsJsonContractResolver()
})
{
this.serializer.Converters.Add(new ReadOnlyObjectCollectionConverter());
this.serializer.Converters.Add(new BusinessObjectCreationConverter());
this.serializer.TraceWriter = new ConsoleTraceWriter();
}
我得到一个例外: 无法将 JSON 对象填充到类型“KS.Interfaces.Core.Entities.EditableObjectCollection`1[KS.Interfaces.Core.Entities.Tests.Unit.EditableObjectCollectionTests+TestEditableObject]”上。路径“$type”,第 1 行,位置 47。
在我的转换器的代码行中:
serializer.Populate(jsonObject.CreateReader(), result);
谁能告诉我可能是什么原因?我很确定我创建了正确的类型并且使用 EditableObjectBase 派生对象一切都很好。只有集合似乎不起作用。
任何提示都非常感谢,在此先感谢 卡斯滕
【问题讨论】:
标签: c# constructor json.net deserialization converter