当前位置:  开发笔记 > 前端 > 正文

JSON.NET和nHibernate Lazy加载集合

如何解决《JSON.NET和nHibernateLazy加载集合》经验,为你挑选了3个好方法。

是否有人使用JSON.NET和nHibernate?我注意到当我尝试加载具有子集合的类时,我遇到了错误.



1> Alireza Sabo..:

我遇到了同样的问题,所以我尝试使用@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);
      }
  }


+1 - 这似乎是NH 3.3和JSON.NET 4.5.7现在唯一的工作版本.

2> Liedman..:

我们有这个确切的问题,这是在Handcraftsman的回应中得到的解决.

问题源于JSON.NET对如何序列化NHibernate的代理类感到困惑.解决方案:将代理实例序列化为基类.

Handcraftsman代码的简化版本如下:

public class NHibernateContractResolver : DefaultContractResolver {
    protected override List GetSerializableMembers(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,我会尝试更新代码.



3> Handcraftsma..:

我使用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 List GetSerializableMembers(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);
      }
    }
  }


感谢您使用此代码,它非常棒!并使我免于使用StatelessSession.
推荐阅读
依然-狠幸福
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有