gpt4 book ai didi

c# - 使用 json.net 支持 ISupportInitialize

转载 作者:行者123 更新时间:2023-11-30 21:52:20 25 4
gpt4 key购买 nike

我正在使用 Newtonsoft json.net 序列化器将我的一些模型序列化为 json。其中一些很复杂,包含循环引用。由于循环引用不可序列化,因此需要通过设置 ReferenceLoopHandling = ReferenceLoopHandling.Ignore 进行处理。使用 ISupportInitialize 在其他序列化之后恢复引用。ISupportInitialize 还用于从数据库初始化大量属性(图像)。有些类没有默认的 ctor(需要 [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]调用 BeginInit()EndInit() 到每个 ISupportInitialize 的回调类型,您可以创建 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/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com