上几篇博文介绍了 业务逻辑层和数据访问层,我认为写博文的作用主要是向业界的读者交流一种思想,点到为止,至于学习架构设计,通过几篇博文是讲不清楚的,还需要【基础】扎实的情况下,【反复】研究【权威】的书籍。
你会发现我写随笔的特点就是喜欢单一,讲NHibernate就绝不会把easyui参合进来,而这次要谈得json也不会和MVC有什么关系。
而实战当中,你会发现我确实可以将他们分开,在需要的时候重新组合各种类库和框架来达到我的目的。
表现层(Presentation Layer)
它主要由两部分组成:
1.界面UI
2.表现层逻辑
界面UI在.NET中包括的几种形式:WEB(ASP.NET)、WPF、WinForm、Mobile
而表现层逻辑通常需要用后台代码做一些事情。
理论上我们应该尽量解除两者之间的依赖,以便于UI更容易切换。
关于表现层的一些误区
1. 觉得拖控件比较低端
由于许多培训学校在解说JAVA和.NET的区别的时候,通常会讲一个能拖控件而一个不能,不能拖控件需要程序员自己写更加高端。
而事实上“拖控件”有个学名的,叫 快速应用程序开发(Rapid Application Development,RAD)。
楼主从学生年代VB/Delphi/C++都是控件拖过来的,到现在也不会觉得它低端,它一种战术。
实际上在传统的ASP.NET中也可以使用MVP模式来做到分离关注点,高不高端,取决于写程序的人,而不在于用什么工具。
就好像昔年兵器谱排名第三的小李飞刀,他的飞刀也只不过是大治的铁匠花了三个时辰打造而成的。
2.关于json的误区
很多人认为json只有在Web开发中有效,甚至认为Easyui+ASP.NET MVC3中间通过json传输数据是唯一的情况。
而事实上我们可以用它作为跨平台的传输格式,WCF正是利用了这一点。
所以对象序列化json的时候,可能ASP.NET MVC3并不是必须的。
设计类库时应该避开对其他框架的依赖。
3.MVC就是ASP.NET MVC x
实际上MVC只是一个模式,而微软对它进行了改进,设计出了ASP.NET MVC框架。
MVC也只不过是WEB应用程序才使用的一种模式,够作为架构设计师,可能需要了解更多。
另外MVC还延伸出几种模式,分别是MVP模式、PM模式。
表现层常用的模式
1.web中
使用传统的ASP.NET,可以适当使用MVP模式分离关注点;
或者使用ASP.NET MVC框架;
2.windows中
使用winForm同样是适当使用MVP模式;
使用WPF可以考虑MVVM模式;
3.移植的考虑
如果你希望你的winForm程序可以移植到Linux换成GTK的话,MVP模式也许是唯一的选择了。
json与DTO的想法
关于Json:ASP.NET MVC框架只能用于WEB应用程序,而json则可以更广泛地应用,所以json序列化的类库与框架的依赖并不是很好的设计。
在winform的项目中,这样的类库拿过来显然就编译不能通过了。
关于DTO:DTO,数据传输对象。理论上在表示层得到数据时应该是DTO,在服务层已经将DataTable/ORM的Model转化成DTO。但实际上这是一个很大的工作量,实际上可能直接使用ORM的Model传输给表现层。
另外服务器端与浏览器传输数据是使用ViewModel,它可以是直接使用ORM的model,也可以是DTO,当然,更复杂的情况是在View需要的数据模型与DTO或者数据库模型不匹配时将组织DTO或者Model根据View需要的属性建立一个ViewModel。
所以我们设计Json序列化类的时候需要考虑几个问题:
1.我们接受的要序列化对象可能是DTO,也可能是ORM的领域模型,而领域模型经常会出现循环依赖,延迟加载。直接用微软自带的序列化类库报错,而使用MVC框架来指定要序列化的属性那么如果不能使用MVC框架又该怎么办?
2.服务器向客户端传输数据的性能考虑,则不应该传输多余的数据。Json序列化时该如何排除不需要的属性?
3.如果是老系统使用.NET,没有微软自带的Json序列化类库,使用第三方类库。
给出简单的解决方案
这里使用了Newtonsoft.Json,并对前人类库进行一些整理,忽略对象循环依赖,能够支持移除不需要的属性。
[Test] public void XLH() { DictionaryRepository rep = new DictionaryRepository(); Dictionary dic = rep.GetByCodeLazy("bianma1", "code1"); string json = Util.Json.Json.Serializer(new { dic ,total=3}, new string[] { "Category" }); Console.WriteLine(json); } [Test] public void FXLH() { string json="{\"Index\":1.0,\"Description\":\"描述1\",\"Id\":\"160954d1-5e73-4ac8-a426-197f5bd616f9\",\"Name\":\"字段1\",\"Code\":\"code1\"}"; Dictionary dc=Util.Json.Json.DeSerializer<Dictionary>(json, null); }
下面两个类可以直接使用。
using System; using System.Collections.Generic; using System.Text; using Newtonsoft.Json; using System.IO; namespace Util.Json { public class Json { /// <summary> /// 序列化 /// </summary> /// <param name="obj"></param> /// <param name="settings"></param> /// <returns></returns> public static string Serializer(object obj, JsonSerializerSettings settings) { JsonSerializer scriptSerializer = JsonSerializer.Create(settings); StringWriter sw = new StringWriter(); scriptSerializer.Serialize(sw, obj); string str = sw.ToString(); sw.Close(); return str; } /// <summary> /// 序列化(忽略对象循环依赖,忽略空值) /// </summary> /// <param name="obj"></param> /// <returns></returns> public static string Serializer(object obj) { JsonSerializerSettings Settings = new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Ignore, NullValueHandling = NullValueHandling.Ignore, DateTimeZoneHandling = DateTimeZoneHandling.Local }; return Serializer(obj, Settings); } /// <summary> /// 序列化(忽略对象循环依赖,忽略空值,排除指定列) /// </summary> /// <param name="obj">序列化目标对象</param> /// <param name="lstExclude">要排除的属性名列表</param> /// <returns></returns> public static string Serializer(object obj,string[] lstExclude) { ExcludePropertiesContractResolver exclude = new ExcludePropertiesContractResolver(lstExclude); JsonSerializerSettings Settings = new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Ignore, NullValueHandling = NullValueHandling.Ignore, DateTimeZoneHandling = DateTimeZoneHandling.Local, ContractResolver = exclude }; return Serializer(obj, Settings); } /// <summary> /// 反序列化 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="str"></param> /// <param name="Settings"></param> /// <returns></returns> public static T DeSerializer<T>(string str, JsonSerializerSettings Settings) { JsonSerializer scriptSerializer = JsonSerializer.Create(Settings); JsonTextReader sr = new JsonTextReader(new StringReader(str)); T obj = scriptSerializer.Deserialize<T>(sr); sr.Close(); return obj; } } }
using System; using System.Collections.Generic; using System.Text; using Newtonsoft.Json.Serialization; using Newtonsoft.Json; namespace Util.Json { /// <summary> /// 重写创建属性列表函数,使之支持排除指定属性 /// </summary> public class ExcludePropertiesContractResolver : DefaultContractResolver { string[] lstExclude; public ExcludePropertiesContractResolver(string[] excludedProperties) { lstExclude = excludedProperties; } protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization) { IList<JsonProperty> list = base.CreateProperties(type, memberSerialization); foreach (string item in lstExclude) { JsonProperty temp = null; foreach (JsonProperty jp in list) { if (jp.PropertyName == item) { temp = jp; } } if (temp != null) { list.Remove(temp); } } return list; } } }