上幾篇博文介紹了 業務邏輯層和數據訪問層,我認為寫博文的作用主要是向業界的讀者交流一種思想,點到為止,至於學習架構設計,通過幾篇博文是講不清楚的,還需要【基礎】扎實的情況下,【反復】研究【權威】的書籍。
你會發現我寫隨筆的特點就是喜歡單一,講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; } } }