c# - 使用 json.net 支持 ISupportInitialize

标签 c# json serialization json.net

我正在使用 Newtonsoft json.net 序列化程序将我的一些模型序列化为 json。 其中一些很复杂,包含循环引用。由于循环引用不可序列化,因此可以通过设置ReferenceLoopHandling = ReferenceLoopHandling.Ignore来处理它们。 在使用 ISupportInitialize 进行其他序列化之后,将恢复引用。 ISupportInitialize 还用于从数据库初始化重要属性(图像)。有些类没有默认构造函数(需要 [NotNull] 参数),我知道我的重属性可能很懒,但由于我的 ISupportInitialize 与以前的序列化器配合得很好(并且经过测试),所以我更愿意使用该机制。

我正在尝试让 json.net 序列化程序检测实现 ISupportInitialize 接口(interface)的类型并调用适当的接口(interface)方法。当实际的序列化/反序列化对象实现接口(interface)时,这很简单,但当对象图中深处的某些属性实现它时,这会更困难(或者至少对我来说不直观)。我尝试编写自定义转换器,但没有运气。下面是我想要完成的一个简单示例

 public class SupportsInitialize : ISupportInitialize
    {
        public void BeginInit(){throw new NotImplementedException();}

        public void EndInit(){throw new NotImplementedException();}
    }

    [Test]
    public void MakeSerializerCallBeginAndEndInit()
    {
        var supportsInitialize = new ToBeSerialized() {SupportsInitialize = new SupportsInitialize()};
        // before serializing any property implementing ISupportInitialize (ToBeSerialized.SupportsInitialize in this case) its BeginInit should be called
        var json = JsonConvert.SerializeObject(supportsInitialize);
        // after deserializing any property implementing ISupportInitialize its EndInit should be called
        var deserialized = JsonConvert.DeserializeObject<ToBeSerialized>(json); 
    }

    public class ToBeSerialized
    {
        public SupportsInitialize SupportsInitialize { get; set; }
    }

感谢您为我指明正确方向的帮助

最佳答案

如果您不想手动添加[OnDeserializing] and [OnDeserialized]对每个 ISupportInitialize 调用 BeginInit()EndInit() 的回调类型,您可以创建 DefaultContractResolver 的自定义子类自动调用适当的方法:

public class ISupportInitializeContractResolver : DefaultContractResolver
{
    // As of 7.0.1, Json.NET suggests using a static instance for "stateless" contract resolvers, for performance reasons.
    // http://www.newtonsoft.com/json/help/html/ContractResolver.htm
    // http://www.newtonsoft.com/json/help/html/M_Newtonsoft_Json_Serialization_DefaultContractResolver__ctor_1.htm
    // "Use the parameterless constructor and cache instances of the contract resolver within your application for optimal performance."
    static ISupportInitializeContractResolver instance;

    // Using a static constructor enables fairly lazy initialization.  http://csharpindepth.com/Articles/General/Singleton.aspx
    static ISupportInitializeContractResolver() { instance = new ISupportInitializeContractResolver(); }

    public static ISupportInitializeContractResolver Instance { get { return instance; } }

    readonly SerializationCallback onDeserializing;
    readonly SerializationCallback onDeserialized;

    protected ISupportInitializeContractResolver()
        : base()
    {
        onDeserializing = (o, context) =>
            {
                var init = o as ISupportInitialize;
                if (init != null)
                    init.BeginInit();
            };
        onDeserialized = (o, context) =>
            {
                var init = o as ISupportInitialize;
                if (init != null)
                    init.EndInit();
            };
    }

    protected override JsonContract CreateContract(Type objectType)
    {
        var contract = base.CreateContract(objectType);
        if (typeof(ISupportInitialize).IsAssignableFrom(objectType))
        {
            contract.OnDeserializingCallbacks.Add(onDeserializing);
            contract.OnDeserializedCallbacks.Add(onDeserialized);
        }
        return contract;
    }
}

然后像这样使用它:

        var settings = new JsonSerializerSettings { ContractResolver = ISupportInitializeContractResolver.Instance };
        var root = JsonConvert.DeserializeObject<ToBeSerialized>(jsonString, settings);

关于c# - 使用 json.net 支持 ISupportInitialize,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34854953/

相关文章:

java - 什么是对象序列化?

json - 反序列化 $ref 和 $id

c# - 将数组从 JavaScript 传递到 C# 的最佳方式?

c# - 如何使用 XAML 在 DataContext 中设置类?

iphone - 带参数的 HTTP POST 请求

javascript - 未捕获语法错误 : Unexpected token < in JSON at position 2 at JSON. 在对象处解析 (<anonymous>)。<anonymous> (userhistory.js:23)

mysql - JSON 更新 MySQL 表中的单个值

java - 如何序列化限制序列化深度的嵌套对象?

c# - 尽管 TransactionScopeOption.Suppress 嵌套事务回滚

c# - 我可以在 ASP.Net 项目的代码隐藏中使用 JSON.Stringify 吗?