﻿# ASP.NET MVC 開發心得分享 (24)：擴充部分類別的建構子

在 ASP.NET MVC 使用 Entity Framework **資料庫先行開發模式** (Database-First Development) 的時候，因為所有 [POCO](http://en.wikipedia.org/wiki/Plain_Old_CLR_Object) (Plain Old CLR Object) 類別都會透過 \*.tt 程式碼產生器範本自動建立，當我們想擴充資料模型時，勢必不會直接把驗證屬性直接寫在這些類別裡，而是在另一個部分類別檔案中，透過 MetadataType 屬性 (Attribute) 宣告一個 Metadata 類別 (又稱 Buddy Class)。另一方面，我們也會在資料模型的 POCO 類別的「建構子」方法中宣告屬性的預設值，但這時問題來了，如果我們在自動產生的資料模型類別中，已經宣告過「建構子」的話，那我們該如何在另一個部分類別檔案中再次「宣告」建構子呢？這就是這篇文章想要解決的難題。

**本次文章教學的範例程式，請從 GitHub 下載，網址如下：  
**[**https://github.com/doggy8088/ExtendPartialClassConstructor**](https://github.com/doggy8088/ExtendPartialClassConstructor)

開啟專案後，你會發現專案中已經完成了 ADO.NET 實體資料模型，以及 Partial 類別的建置：

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/6f8f07293e521b191c78-image_2135.png)

我們先開啟 Client.cs 資料模型類別來看，由於 Client 與 Order 的關係是一對多的關係，所以在自動產生的 POCO 類別中，也將會自動建立出一個預設的 **建構子** (Constructor)，並在裡面定義 Order 這個屬性的預設資料。

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/4c342e3c8ebab381ac2b-image_2136.png)

這時我們再開啟 Client.Partial.cs 檔案來看，目前這個檔案的內容是空的，因為要在部分類別中無法再次定義原本部分類別中已經有的屬性名稱，所以必須透過 Buddy Class 宣告，並把驗證屬性都定義在另一個 Metadata 類別裡面。

**註**：請參考 [ASP.NET MVC 4 開發實戰](https://web.archive.org/web/20191112080721/https://www.delightpress.com.tw/book.aspx?book_id=sknp00028) 的 **5-7-1 定義資料模型的 Metadata** 小節 , 第 192 頁。

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/a1757514d4ab2d4a0ff9-image_2137.png)

例如我們因為專案需求，需要在程式中加入特定欄位的預設值，以此案為例，我們假設要把 Client 實體的 City 欄位，給予一個預設值為「台北市」，那麼你可以在 Client.cs 檔案中加入以下程式碼片段：

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/75285954cd19f3974c0d-image_2138.png)

但因為 Client.cs 是自動產生的，每當你修正 EDMX 實體資料模型檔，就會導致檔案被重新產生，也意味著你所做出的任何變更都會被蓋掉！

如果你想試圖在 Client.Partial.cs 檔案加入建構子的話，那自然也是行不通的，如下圖示：

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/4d6d6849de205c85a40a-image_2139.png)

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/86a432e99ec9ace4b193-image_2140.png)

對於這個問題，應該如何解決呢？

我們可以利用 C# 的 **[部分方法](http://msdn.microsoft.com/zh-tw/library/vstudio/6b0scde8.aspx)** ([partial method](http://msdn.microsoft.com/en-us/library/vstudio/6b0scde8.aspx)) 來嘗試解決這個問題！

> **備註：**在定義部分方法時，請注意以下條件，必須都成立才能宣告部分方法：
> 
> -   部分型別兩個部分中的簽章必須相符。
> -   方法必須傳回 void。
> -   不允許存取修飾詞 (Modifier) 或屬性。 部分方法都是隱含的私用方法。

首先，我們現在 Client.cs 檔案中新增一個 [**部分方法**](http://msdn.microsoft.com/zh-tw/library/vstudio/6b0scde8.aspx) 的簽章 (Signature)，如下圖示：

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/e9bc7de5c6459f92685a-image_2141.png)

我們接著在回到 Client.Partial.cs 檔案加入 Initialize() 部分方法實作，就可以解決這次的問題！

![image](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/4315ac7c712aae80718a-image_2142.png "image")

不過，我之前在【**ASP.NET MVC 4 開發實戰**】的教學課程中，也有人提到：  
「**我們在 Client.cs 中修改過的程式碼，當實體資料模型異動時，不是一樣會被蓋掉嗎？**」

是的，的確還是會被蓋掉，所以我們還必須修改負責產生 POCO 類別的 \*.tt 檔，這個程式碼範本檔並不會因為 ADO.NET 實體資料模型的變更而被蓋掉，所以各位可以放心修改：

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/a1d670f6f19cebaaf49c-image_2143.png)

開啟後，直接參考如下圖示，跳到相對應的行數，加入這兩行即可：

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/f9d7c6e4286239aa6581-image_2144.png)

如此一來，所有自動產生的 POCO 模型類別就會自動包含所有 Initialize() 部分方法的定義了！ (^\_^)

**相關連結**

-   [Plain Old CLR Object - Wikipedia, the free encyclopedia](http://en.wikipedia.org/wiki/Plain_Old_CLR_Object)
-   [partial (Method) (C# Reference)](http://msdn.microsoft.com/en-us/library/vstudio/6b0scde8.aspx) / [partial (方法) (C# 參考)](http://msdn.microsoft.com/zh-tw/library/vstudio/6b0scde8.aspx)
