• Asp.Net MVC大型项目实践整合 NHibernate与Json序列化


    通过NHibernate我们多表查询是实现了 但由于查询出来的集合中的对象“不是平的”,如何在送到UI绑定成了问题。ExtJs UI组件的数据绑定支持多种格式,如简单数组,Json,Xml。在本项目中我们统一,服务器端通过Json把数据传输到Ext进行解析和绑定。

    那么我们现在只需要找个方便的办法把我们的.Net对象(集合)转化为Json格式的字符串就可以了。于是乎我们google了一下发现.Net下还真有这么个方法能把.Net对象序列化成Json字符串
    new System.Web.Script.Serialization.JavaScriptSerializer().Serialize([要序列化的.Net对象]);
    Asp.Net Mvc里也有(看过MVC源码后可知,其实里面用的也是上面的JavaScriptSerializer):

    public ActionResult test5()
    {
    return Json([要序列化的Json对象]);
    }

    我们试试

    //Json输出试一试
    public ActionResult test5()
    {
    return Json(new {
    Name = "弦哥",
    Age = 26,
    IsMarry = true,
    MyDog = new { Name = "大海", Age = 1, Variety="罗威纳" }
    });}

    输出的Json字符串为:{"Name":"弦哥","Age":26,"IsMarry":true,"MyDog":{"Name":"大海","Age":1,"Variety":"罗威纳"}}

    但把NHibernate查询出的集合对象也放进去序列化一下:出现错误了,序列化类型对象的时候检测到对象循环使用。

    解决方法:

    我们用Json.Net(Newtonsoft.Json),下面我们继承他的DefaultContractResolver类并重写GetSerializableMembers方法 ,定义我们自己的Json序列化规则NHibernateContractResolver,代码如下:

    View Code
    namespace Demo.HIS.FrameWork
    {
    /// <summary>
    /// 自定义Json.Net的规则
    /// </summary>
    public class NHibernateContractResolver : DefaultContractResolver
    {
    private string[] exceptMemberName;//例外
    
    private static readonly MemberInfo[] NHibernateProxyInterfaceMembers = typeof(INHibernateProxy).GetMembers();
    
    public NHibernateContractResolver(string[] exceptMemberName)
    {
    this.exceptMemberName = exceptMemberName;
    }
    protected override List<MemberInfo> GetSerializableMembers(Type objectType)
    {
    var members = new List<PropertyInfo>(objectType.GetProperties());
    members.RemoveAll(memberInfo =>
    // (IsMemberNames(memberInfo))||
    (IsMemberPartOfNHibernateProxyInterface(memberInfo))||
    (IsMemberDynamicProxyMixin(memberInfo))||
    (IsMemberMarkedWithIgnoreAttribute(memberInfo,objectType))||
    (IsInheritedISet(memberInfo))||
    (IsInheritedEntity(memberInfo))
    );
    
    var actualMemberInfos = new List<MemberInfo>();
    foreach (var memberInfo in members)
    {
    var infos = memberInfo.DeclaringType.BaseType.GetMember(memberInfo.Name);
    actualMemberInfos.Add(infos.Length == 0 ? memberInfo : infos[0]);
    //Debug.WriteLine(memberInfo.Name);
    }
    return actualMemberInfos;
    }
    private static bool IsMemberDynamicProxyMixin(PropertyInfo memberInfo)
    {
    return memberInfo.Name == "__interceptors";
    }
    
    private static bool IsMemberPartOfNHibernateProxyInterface(PropertyInfo memberInfo)
    {
    return Array.Exists(NHibernateProxyInterfaceMembers, mi => memberInfo.Name == mi.Name);
    }
    
    private static bool IsMemberMarkedWithIgnoreAttribute(PropertyInfo 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 bool IsExceptMember(PropertyInfo memberInfo)
    {
    if (exceptMemberName == null)
    return false;
    return Array.Exists(exceptMemberName, i => memberInfo.Name == i);
    }
    
    private bool IsInheritedISet(PropertyInfo memberInfo)
    {
    return (memberInfo.PropertyType.Name == "ISet`1" && !IsExceptMember(memberInfo));
    }
    
    private bool IsInheritedEntity(PropertyInfo memberInfo)
    {
    return (FindBaseType(memberInfo.PropertyType).Name == "Entity" && !IsExceptMember(memberInfo));
    }
    private static Type FindBaseType(Type type)
    {
    if (!type.IsClass)
    return type;
    if (type.Name == "Entity"||type.Name=="Object")
    {
    return type;
    }
    return FindBaseType(type.BaseType);
    }
    }
    }

    代码有点复杂,涉及到对NHibernate动态代理的一些特殊处理。大概意思就是如果对象里的属性的类型为Entity或ISet<T>的我们就忽略掉,不序列化,除非我们显示指定需要序列化的属性名。

    为了方便Asp.Net MVC调用我们自己的Json序列化,我们自定义一个ActionResult:

    View Code
    public class FormatJsonResult : ActionResult
    {
    public string[] ExceptMemberName { get; set; }
    public Object Data { get; set; }
    public override void ExecuteResult(ControllerContext context)
    {
    if (context == null)
    {
    throw new ArgumentNullException("context");
    }
    HttpResponseBase response = context.HttpContext.Response;
    response.ContentType = "application/json";
    
    StringWriter sw = new StringWriter();
    JsonSerializer serializer = JsonSerializer.Create(
    new JsonSerializerSettings
    {
    Converters = new JsonConverter[] { new Newtonsoft.Json.Converters.JavaScriptDateTimeConverter() },
    ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
    NullValueHandling = NullValueHandling.Ignore,
    ContractResolver = new NHibernateContractResolver(ExceptMemberName)
    }
    );
    
    using (JsonWriter jsonWriter = new JsonTextWriter(sw))
    {
    jsonWriter.Formatting = Formatting.Indented;
    serializer.Serialize(jsonWriter, Data);
    }
    response.Write(sw.ToString());
    }
    }

    再给Asp.net MVC的Controller类定义两个扩展方法:

    View Code
    public static class FormatJsonExtension
    {
    public static FormatJsonResult JsonFormat(this Controller c, object data, string[] exceptMemberName)
    {
    FormatJsonResult result = new FormatJsonResult();
    result.Data = data;
    result.ExceptMemberName = exceptMemberName;
    return result;
    }
    
    public static FormatJsonResult JsonFormat(this Controller c, object data)
    {
    return JsonFormat(c, data, null);
    }
    
    }

    //测试一下
    public ActionResult test()
    {
    Demo.HIS.Infrastructure.Core.Repositories.IDictionaryRepository r = new Demo.HIS.Infrastructure.Repositories.Data.DictionaryRepositoryImpl();
    long total;
    var list = r.GetPlistByCategoryId("48391bb4-471b-4499-899b-cea9748e1a7b", 0, 15, "Index", "desc", null, out total);

    //我们自己的Json序列化方法
    return this.JsonFormat(
    list,
    new string[] { "Category" });//指定需要序列化属性“Category”
    }

  • 相关阅读:
    Nginx虚拟主机配置实例(Nginx VirtualHost Example)
    考研机试 33.密码翻译
    考研机试 26.10进制 VS 2进制
    考研机试 25.剩下的树
    input默认值设置
    http 304优化,了解客户端缓存
    (转)8款在线CSS优化工具/组织和压缩CSS
    照片从模糊到清晰的渐变加载显示方法
    JS压缩工具Closure Compiler 和 YUICompressor的对比
    【转】高性能web开发 如何加载JS,JS应该放在什么位置?
  • 原文地址:https://www.cnblogs.com/aaa6818162/p/4606689.html
Copyright © 2020-2023  润新知