7

これは私がこのサイトで尋ねる最初の質問なので、何か見逃していたらすみません。

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 インスタンスが私が知らない型のオブジェクトに含まれていると、考えはさらに複雑になります。この場合、コンバーターが呼び出されることも必要です。

前もって感謝します、カルステン

4

1 に答える 1

0

シリアル化または逆シリアル化するクラスに [DataContract] 属性を与え、これらのクラスに含まれるデータがこの属性も持っていることを確認してください。例えば

[DataContract]
public class TestBusinessObject : BusinessObjectBase
{
    protected TestBusinessObject(SerializationContext context)
        : base(context)
    {{
    }

    public NestedObject InnerObject { get; set; }
}
于 2014-11-20T11:51:48.450 に答える