天天看點

一起談.NET技術,Visual Studio 2010層架構驗證的實作

  當設計一個應用程式時,基本的要求是所有的通信資訊互動都要通過定義的接口進行,不能讓應用程式直接調用該接口的類别或方法。是以,可以通過Layer Diagram來展示這個架構上的想法。

  我們将使用一段非常簡單的代碼,主要強調的是代碼所代表的概念,而不是代碼的細節。并将在現有代碼層關系架構邏輯設計分析的基礎上進行層驗證(Layer Validation)功能:

  ①打開Visual Studio 2010,通過Modeling Projects模闆指定解決方案(Solution)的名稱為LayerValidation(File|New|Project指令,選擇ModelingProject,命名為LayerValidation),并提供建立一個名為“Client”的C#控制台程式,單擊“OK”按鈕。

  ②在解決方案浏覽器中,使用滑鼠右鍵單擊Solution節點,選擇“New Project…”指令,在彈出的對話框中選擇“Class Library”并将工程命名為“Implementation”。

  ③重複以上幾步,建立名為“Interfaces”和“Creators”的Class Library工程。展開Interfaces工程節點,用滑鼠右鍵單擊Class1.cs,選擇“Rename”指令,将該檔案重命名為“IDataRetriever.cs”,并在彈出的對話框中選擇“Yes”。文檔編輯視窗和Solution Explorer如圖5所示。

一起談.NET技術,Visual Studio 2010層架構驗證的實作
一起談.NET技術,Visual Studio 2010層架構驗證的實作

圖5  文檔編輯視窗和Solution Explorer

  ④把class的關鍵字改為interface,将IDataRetriever變成一個接口。為IDataRetriever添加一個get屬性,該屬性傳回一個IData類型的對象。在IData下面有紅色波浪線,表示IData不存在。Visual Studio 2010的新功能可以自動解決這個問題:用滑鼠右鍵單擊出錯的IData,選擇“Generate”指令,然後選擇“Other…”指令,将看到一個“New Type”對話框。将其中的“Access:”修改為“public”,将“Kind:”修改為“interface”,其他的保留預設設定,單擊“OK”按鈕。VS會自動向Interfaces工程添加一個IData.cs檔案,并在檔案中建立一個名為IData的接口。

  ⑤展開Implementation工程節點,用滑鼠右鍵單擊References節點,選擇“Add Reference…”指令,在彈出的對話框中選擇Projects頁,然後選擇Interfaces工程,單擊“OK”按鈕。

  ⑥将Class1.cs重命名為DataRetriever.cs。打開DataRetriever.cs檔案,修改DataRetriever類使其實作IDataRetriever接口。當輸入IDataRetriever的時候沒有出現智能輸入支援,可以手動輸入IDataRetriever,然後會發現IDataRetriever下面又出現了紅色波浪線。将滑鼠移動到IDataRetriever上,會注意到在這個單詞開始的位置下方有一個方形的小圖示。單擊它并選擇“using Interfaces;”指令,它會自動為你添加所需的using語句,如圖6所示。 

一起談.NET技術,Visual Studio 2010層架構驗證的實作

圖6  自動化提示添加代碼語句(名字空間)

  現在“using Interfaces”已經自動添加好了。再次選中這個圖示,不過這次選擇“Implement interface ‘IDataRetriever’”指令,可自動生成“DataRetriever”代碼檔案。如上所示,建立了一個對象,調用了對象的一個屬性,然後抛出一個“NotImplementedException”異常,程式描述了一個實際系統中經常遇到的問題。

  ⑧接下來向Client工程中添加到Implementation和Interfaces工程的引用。打開Client工程中的Program.cs檔案,參考代碼如下:

using System;

using System.Collections.Generic;

. using System.Linq;

using System.Text;

using Implementation;

using Interfaces;

namespace Client

{

class Program

static void Main(string[] args)

DataRetriever dr = new DataRetriever();

IData data = dr.Data;

}

  在這段代碼中,Client工程直接通路了一個接口(IDataRetriever)的執行個體(DataRetriever)。在沒有需求功能擴充前沒有太大問題,因為所有的資料是從DataRetriever中擷取(可以想象DataRetriever是從SQL資料庫中擷取的資料)。如果将來需要從另一種資料源中擷取資料,在不改動應用程式其他部分的情況下實作需求,可以使用Layer Diagram和Layer Validation來保證開發代碼不會違反這一設計。

  我們可以不對接口的具體實作做任何設定,而僅僅依賴于接口本身。這是一個相當普遍的設計模式,但是在現實應用中很容易被違反。隻要一行錯誤的代碼就會破壞這個模式,進而在建立子產品間出現了不必要的依賴關系(通常使用控制反轉(IoC)來解決這個問題)。

  ⑨建立Layer Diagram。可以建立一個Layer Diagram來可視化地描述在架構中想要維護的限制關系。單擊主菜單的Architecture|New Diagram指令,選擇“Layer Diagram”指令,并将層圖命名為“FirstLayerDiagram.layerdiagram”,在彈出的對話框中,将工程命名為“FirstModelingProject”。

  ⑩塑模範本,将代碼映射到層上。在Layer Diagram Designer中,從工具箱中拖曳出三個Layer工具到設計平面上,分别由上至下指定層的名稱為Client、Interface、Implementation,代表應用程式、工作接口和方法。表示的是Client Logic層依賴于Interfaces層,Implementation層同樣依賴于Interfaces層。但是Client Logic層和Implementation層之間沒有依賴關系,如圖7所示。

一起談.NET技術,Visual Studio 2010層架構驗證的實作

圖7  建立映射

  如上圖所示,然後建立各個層次之間的互相關系。從工具箱中選擇Dependency工具,在Solution Explorer中,選中Client工程并将它拖曳到Layer Diagram上的Client Logic層上,代表Client層會依賴Interface層。這時出現了一個由Client指向Interface的箭頭連結。将Interfaces工程拖到Interfaces層上;最後,将Implementation工程拖到Implementation層上,代表Implementation層會依賴Interface層;在層右上角的數字“1”表示該層已經和一個工程相關聯。

  如果選中Client Logic、Interfaces和Implementation層,再打開Layer Explorer,就可以看到和目前層關聯的項目,這裡是Client.exe、Interfaces.dll和Implementation.dll,然後就可以用這張圖來對代碼進行限制與驗證,如圖8所示。 

一起談.NET技術,Visual Studio 2010層架構驗證的實作

圖8  進行架構驗證

  如上圖所示,進行架構驗證。用滑鼠右鍵單擊Layer Diagram的任何位置,選擇“Validate Architecture”指令,進行驗證。

  驗證架構(Validate Architecture):可以檢查出我們的程式是否破壞了層次圖中的依賴關系,如果我們的程式中的CaryLayer項目中的程式調用了Common項目中的類等于就違反了以前設計好的層次圖,在驗證架構的時候就會失敗。

  依賴關系(Generate Dependencies):可以根據我們程式中的調用關系生成層的依賴關系。

  錯誤清單。指令執行完成後會看到“Error List”視窗中有三條錯誤資訊,同時訓示錯誤發生的區域。檢視一下錯誤内容,會發現我們要求的層次依賴關系被破壞了。這是因為Client工程中的Program.cs直接使用了Implementation工程中定義的類型。而在剛才建立的圖中,這種依賴關系是錯誤的,如圖3錯誤清單提示。

  修正代碼,解決錯誤問題。

  打開Program.cs檔案,需要確定隻使用Interfaces工程中定義的類型,而不能直接使用Implementation工程中定義的類型。我們需要在不産生直接依賴關系的情況下建立實作IDataRetriever接口的對象。

  解決方法是使用Factory模式,利用Factory建立以接口為主的方法。當以後要傳回的資訊接收器是針對不同的資訊來源進行處理的,隻要調整Factory方法傳回對應的接收器即可,原本的應用程式不用改動,因為它都是通過接口決定作業的,隻要實做了同樣接口的類都可以套用,進而增加了程式的彈性和維護能力。使用工廠(Factory)模式來解決這個問題的步驟如下:

  在Solution Explorer中展開Creators工程,将Class1.cs重命名為TypeCreator.cs。

  向Creators工程中添加對Implementation和“Interfaces”工程的引用(Creators工程現在依賴于Implementation和Interfaces工程)。

  打開TypeCreators.cs,向其中添加一個靜态方法,該方法傳回一個IDataRetriever的對象。

代碼參考如下所示:

using System.Linq;

namespace Creators

public class TypeCreator

public static IDataRetriever CreateDataRetriever()

return new DataRetriever();

  在Client工程中,移除對Implementation工程的引用,添加對Creators工程的引用。

  修改Program.cs,使用剛才新加的方法來建立對象。代碼參考如下所示:

using Creators;

IDataRetriever dr = new TypeCreator.CreateDataRetriever();

  重新編譯Solution,并重新打開FirstLayerDiagram,用滑鼠右鍵單擊,在菜單中執行“Validate Architecture”指令。這樣我們就不是直接通過實做的類進行資訊的存取,而是經由Factory取得符合接口定義的内容。再做一次層驗證,我們會看到所有的錯誤都消失了。

  總結:通過使用Visual Studio 2010層關系設計架構,我們就可以在開始階段通過層關系圖來進行邏輯設計,并努力執行設計方案,保證開發階段與設計不偏離,通過自動化(例如門控簽入)進行強制執行,使團隊人員的代碼不漂移出架構,進而避免“漂移”發生。另外,采用Layer Diagram來驗證代碼架構的方法,大型項目也可以通過相同的方式進行驗證。這包括如何将代碼映射到層上,以及如何通過手動的方式來驗證代碼是否遵守定義的限制關系,也可以在編譯代碼的過程中自動地進行驗證。