【发布时间】:2016-09-03 06:27:45
【问题描述】:
我正在尝试使用 JSON.NET 实现 IDeserializationCallback。我正在反序列化一个对象,我想生成一个列表,其中包含所有实现 IDeserializationCallback 的反序列化对象,最好的方法是什么? JSON.NET 是否有任何适当的扩展点来促进这一点?我在下面有一个(看似)有效的解决方案,但是它非常难看,所以我相信必须有更好的方法来做到这一点。任何帮助表示赞赏,谢谢!
private static JsonSerializer serializer = new JsonSerializer();
static cctor()
{
serializer.Converters.Add(new DeserializationCallbackConverter());
}
public static T Deserialize<T>(byte[] data)
{
using (var reader = new JsonTextReader(new StreamReader(new MemoryStream(data))))
using (DeserializationCallbackConverter.NewDeserializationCallbackBlock(reader))
return serializer.Deserialize<T>(reader);
}
private class DeserializationCallbackConverter : JsonConverter
{
[ThreadStatic]
private static ScopedConverter currentConverter;
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
return currentConverter.ReadJson(reader, objectType, serializer);
}
public override bool CanConvert(Type objectType)
{
return currentConverter == null ? false : currentConverter.CanConvert();
}
public override bool CanWrite
{
get { return false; }
}
public static IDisposable NewDeserializationCallbackBlock(JsonReader reader)
{
return new ScopedConverter(reader);
}
private class ScopedConverter : IDisposable
{
private JsonReader jsonReader;
private string currentPath;
private List<IDeserializationCallback> callbackObjects;
public ScopedConverter(JsonReader reader)
{
jsonReader = reader;
callbackObjects = new List<IDeserializationCallback>();
currentConverter = this;
}
public object ReadJson(JsonReader reader, Type objectType, JsonSerializer serializer)
{
var lastPath = currentPath;
currentPath = reader.Path;
var obj = serializer.Deserialize(reader, objectType);
currentPath = lastPath;
var dc = obj as IDeserializationCallback;
if (dc != null && callbackObjects != null)
callbackObjects.Add(dc);
return obj;
}
public bool CanConvert()
{
return jsonReader.Path != currentPath;
}
public void Dispose()
{
currentConverter = null;
foreach (var obj in callbackObjects)
obj.OnDeserialization(null);
}
}
}
【问题讨论】:
-
我想你是想traverse 图表并填充一个列表,以便图表中的每个节点也被列表中的一个项目引用,对吧?
-
您尝试过基于反射的方法吗?根据我的经验,它不是很慢。
-
雷南:是的,没错
-
那么请看this article。您必须访问图中的每个对象一次,然后在列表中保留对它的引用。这是最有效的方法之一。请不要在这样的任务中使用反射,因为它不仅效率不高,而且可能会为不良做法打开大门,这些做法以后会再次困扰您。
-
任何代码/数据来显示您的问题,以便我们可以加快速度?