これは私がこのサイトで尋ねる最初の質問なので、何か見逃していたらすみません。
JSON.NET を使用して複雑なオブジェクト グラフを逆シリアル化する際に問題があります。私のクラス階層は(簡略化して)次のとおりです。
public abstract class BusinessObjectBase
{
protected BusinessObjectBase(SerializationContext context)
{
}
}
public class TestBusinessObject : BusinessObjectBase
{
protected TestBusinessObject(SerializationContext context)
: base(context)
{
}
public NestedObject InnerObject { get; set; }
}
public class NestedObject : BusinessObjectBase
{
protected NestedObject(SerializationContext context)
: base(context)
{
}
}
クラスにはデフォルトの ctor はありませんが、例に示すように、専用のカスタム逆シリアル化 ctor (パラメーターを持つ他のパブリック ctor の横) があります。インスタンスを作成するために、次のようなカスタム作成コンバーターを作成しました。
internal class BusinessObjectCreationConverter : CustomCreationConverter<BusinessObjectBase>
{
public override bool CanConvert(Type objectType)
{
return typeof(BusinessObjectBase).IsAssignableFrom(objectType) && !objectType.IsAbstract;
}
public override BusinessObjectBase Create(Type objectType)
{
var businessObject = objectType.CreateUsingDesrializationConstructor<BusinessObjectBase>();
return businessObject;
}
}
CreateUsingDesrializationConstructor() 拡張メソッドは、特殊な逆シリアル化 ctor を探し、ctor を使用してインスタンスを作成します。
JSON.NET シリアライザー インスタンスへのコンバーターに追加しました。
public class NewtonsoftJsonSerializer : ISerializer
{
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 BusinessObjectCreationConverter());
}
public T Deserialize<T>(Stream stream)
{
T result;
using (var streamReader = new StreamReader(stream, Encoding.UTF8, true, BufferSize, true))
using (var jsonReader = new JsonTextReader(streamReader))
{
result = this.serializer.Deserialize<T>(jsonReader);
}
return result;
}
}
TestBusinessObject を逆シリアル化すると、デバッガーから、コンバーターがインスタンスを作成できるかどうかをすべての型 (TestBusinessObject、NestedObject、およびその他の多くの型) について尋ねていることがわかります。しかし、私のコンバーターは、新しい TestBusinessObject インスタンスを作成することのみを要求されます。デシリアライゼーション ctor にはワイヤード ロジックがあるため、ネストされた NestedObject インスタンスを作成することは要求されません。
ここで私が間違っているのは、JsonSerializer に、ルート (トップレベル) オブジェクトではなく、すべてのオブジェクトに対してコンバーターを使用するように指示する方法ですか?
編集: BusinessObjectBase インスタンスが私が知らない型のオブジェクトに含まれていると、考えはさらに複雑になります。この場合、コンバーターが呼び出されることも必要です。
前もって感謝します、カルステン