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”
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值