是否有人使用JSON.NET和nHibernate?我注意到当我尝试加载具有子集合的类时,我遇到了错误.
我遇到了同样的问题,所以我尝试使用@Liedman的代码,但是GetSerializableMembers()
从来没有调用代理引用.我发现了另一种覆盖方法:
public class NHibernateContractResolver : DefaultContractResolver { protected override JsonContract CreateContract(Type objectType) { if (typeof(NHibernate.Proxy.INHibernateProxy).IsAssignableFrom(objectType)) return base.CreateContract(objectType.BaseType); else return base.CreateContract(objectType); } }
我们有这个确切的问题,这是在Handcraftsman的回应中得到的解决.
问题源于JSON.NET对如何序列化NHibernate的代理类感到困惑.解决方案:将代理实例序列化为基类.
Handcraftsman代码的简化版本如下:
public class NHibernateContractResolver : DefaultContractResolver { protected override ListGetSerializableMembers(Type objectType) { if (typeof(INHibernateProxy).IsAssignableFrom(objectType)) { return base.GetSerializableMembers(objectType.BaseType); } else { return base.GetSerializableMembers(objectType); } } }
恕我直言,这段代码的优势仍然是依赖于JSON.NET关于自定义属性等的默认行为(并且代码更短!).
它像这样使用
var serializer = new JsonSerializer{ ReferenceLoopHandling = ReferenceLoopHandling.Ignore, ContractResolver = new NHibernateContractResolver() }; StringWriter stringWriter = new StringWriter(); JsonWriter jsonWriter = new Newtonsoft.Json.JsonTextWriter(stringWriter); serializer.Serialize(jsonWriter, objectToSerialize); string serializedObject = stringWriter.ToString();
注意:此代码是为NHibernate 2.1编写并使用的.正如一些评论者指出的那样,它不能与更新版本的NHibernate一起开箱即用,你将不得不做一些调整.如果我必须使用更新版本的NHibernate,我会尝试更新代码.
我使用NHibernate和Json.NET,并注意到我在序列化对象中得到了莫名其妙的"__interceptors"属性.谷歌搜索出现了Lee Henson的这个出色的解决方案,我适应了Json.NET 3.5 Release 5,如下所示.
public class NHibernateContractResolver : DefaultContractResolver { private static readonly MemberInfo[] NHibernateProxyInterfaceMembers = typeof(INHibernateProxy).GetMembers(); protected override ListGetSerializableMembers(Type objectType) { var members = base.GetSerializableMembers(objectType); members.RemoveAll(memberInfo => (IsMemberPartOfNHibernateProxyInterface(memberInfo)) || (IsMemberDynamicProxyMixin(memberInfo)) || (IsMemberMarkedWithIgnoreAttribute(memberInfo, objectType)) || (IsMemberInheritedFromProxySuperclass(memberInfo, objectType))); var actualMemberInfos = new List (); foreach (var memberInfo in members) { var infos = memberInfo.DeclaringType.BaseType.GetMember(memberInfo.Name); actualMemberInfos.Add(infos.Length == 0 ? memberInfo : infos[0]); } return actualMemberInfos; } private static bool IsMemberDynamicProxyMixin(MemberInfo memberInfo) { return memberInfo.Name == "__interceptors"; } private static bool IsMemberInheritedFromProxySuperclass(MemberInfo memberInfo, Type objectType) { return memberInfo.DeclaringType.Assembly == typeof(INHibernateProxy).Assembly; } private static bool IsMemberMarkedWithIgnoreAttribute(MemberInfo memberInfo, Type objectType) { var infos = typeof(INHibernateProxy).IsAssignableFrom(objectType) ? objectType.BaseType.GetMember(memberInfo.Name) : objectType.GetMember(memberInfo.Name); return infos[0].GetCustomAttributes(typeof(JsonIgnoreAttribute), true).Length > 0; } private static bool IsMemberPartOfNHibernateProxyInterface(MemberInfo memberInfo) { return Array.Exists(NHibernateProxyInterfaceMembers, mi => memberInfo.Name == mi.Name); } }
要使用它,只需在JsonSerializer的ContractResolver属性中放置一个实例.可以通过将ReferenceLoopHandling属性设置为ReferenceLoopHandling.Ignore来解决jishi指出的循环依赖问题.这是一个扩展方法,可用于使用Json.Net序列化对象
public static void SerializeToJsonFile(this T itemToSerialize, string filePath) { using (StreamWriter streamWriter = new StreamWriter(filePath)) { using (JsonWriter jsonWriter = new JsonTextWriter(streamWriter)) { jsonWriter.Formatting = Formatting.Indented; JsonSerializer serializer = new JsonSerializer { NullValueHandling = NullValueHandling.Ignore, ReferenceLoopHandling = ReferenceLoopHandling.Ignore, ContractResolver = new NHibernateContractResolver(), }; serializer.Serialize(jsonWriter, itemToSerialize); } } }