自訂檔案儲存體和 XML 序列化
當使用者在 Visual Studio 中儲存特定領域語言 (DSL) 的執行個體或模型時,就會建立或更新 XML 檔案。 檔案可以重新載入以在市集中重新建立模型。
您可以藉由在 DSL 總管中的 XML 序列化行為下調整設定,自訂序列化配置。 每個領域類別、屬性和關聯性在 XML 序列化行為底下都有節點。 關聯性位於其來源類別底下。 也有對應至圖形、連接器和圖表類別的節點。
您也可以撰寫程式碼以進行更進階的自訂。
注意
如果您想要以特定格式儲存模型,但不需要從該表單重新載入模型,請考慮使用文字範本從模型產生輸出,而不是自訂序列化配置。 如需詳細資訊,請參閱從特定領域語言產生程式碼。
模型和圖表檔案
每個模型通常會儲存在兩個檔案中:
模型檔案具有例如 Model1.mydsl 的名稱。 會儲存模型元素和關聯性及其屬性。 .mydsl 之類的副檔名是由 DSL 定義中編輯器節點的 FileExtension 屬性所決定。
圖表檔案具有例如 Model1.mydsl.diagram 的名稱。 會儲存圖形、連接器及其位置、色彩、線條粗細,以及圖表外觀的其他詳細資料。 如果使用者刪除 .diagram 檔案,模型中的基本資訊不會遺失。 只有圖表配置會遺失。 開啟模型檔案時,將會建立一組預設的圖形和連接器。
變更 DSL 副檔名
開啟 DSL 定義。 在 [DSL 總管] 中,按一下 [編輯器] 節點。
在 [屬性] 視窗中,編輯 FileExtension 屬性。 不包含副檔名的初始 "."。
在 [方案總管] 中,變更 DslPackage\ProjectItemTemplates 中兩個項目範本檔案的名稱。 這些檔案具有遵循以下格式的名稱:
myDsl.diagram
myDsl.myDsl
預設序列化配置
為了建立此主題的範例,使用了下列 DSL 定義。
此 DSL 是用來建立在螢幕上具有下列外觀的模型。
此模型已儲存,然後在 XML 文字編輯器中重新開啟:
<?xml version="1.0" encoding="utf-8"?>
<familyTreeModel xmlns:dm0="http://schemas.microsoft.com/VisualStudio/2008/DslTools/Core" dslVersion="1.0.0.0" Id="f817b728-e920-458e-bb99-98edc469d78f" xmlns="http://schemas.microsoft.com/dsltools/FamilyTree">
<people>
<person name="Henry VIII" birthYear="1491" deathYear="1547" age="519">
<children>
<personMoniker name="/f817b728-e920-458e-bb99-98edc469d78f/Elizabeth I" />
<personMoniker name="/f817b728-e920-458e-bb99-98edc469d78f/Mary" />
</children>
</person>
<person name="Elizabeth I" birthYear="1533" deathYear="1603" age="477" />
<person name="Mary" birthYear="1515" deathYear="1558" age="495" />
</people>
</familyTreeModel>
請注意有關序列化模型的下列重點:
每個 XML 節點都具有與領域類別名稱相同的名稱,但是初始字母為小寫。 例如,
familyTreeModel
與person
。Name 和 BirthYear 等領域屬性會序列化為 XML 節點中的屬性。 同樣地,屬性名稱的初始字元會轉換成小寫。
每個關聯性都會序列化為在關聯性來源端內成為巢狀的 XML 節點。 節點具有與來源角色屬性相同的名稱,但是初始字元為小寫。
例如,在 DSL 定義中,People 的角色其來源為 FamilyTree 類別。 在 XML 中,這會由在
familyTreeModel
節點內成為巢狀、名為people
的節點表示。每個內嵌關聯性的目標端都會序列化為在關聯性下巢狀的節點。 例如,
people
節點包含數個person
節點。每個參考關聯性的目標端都會序列化為 Moniker,將參考編碼為目標元素。
例如,在
person
節點下,可能會有children
關聯性。 此節點包含 Moniker,例如:<personMoniker name="/f817b728-e920-458e-bb99-98edc469d78f/Elizabeth I" />
了解 Moniker
Moniker 是用來代表模型與圖表檔案的不同部分之間的交叉參考。 它們也會用於 .diagram
檔案中,以參考模型檔案中的節點。 Moniker 有兩種形式:
識別碼 Moniker 會引用目標元素的 GUID。 例如:
<personShapeMoniker Id="f79734c0-3da1-4d72-9514-848fa9e75157" />
限定索引鍵 Moniker 會以名為 Moniker 索引鍵的指定領域屬性值識別目標元素。 目標元素的 Moniker 前面會加上內嵌關聯性樹狀結構中其父元素的 Moniker。
下列範例取自 DSL,其中有名為 Album 的領域類別,其與名為 Song 的領域類別有內嵌關聯性:
<albumMoniker title="/My Favorites/Jazz after Teatime" /> <songMoniker title="/My Favorites/Jazz after Teatime/Hot tea" />
如果目標類別具有領域屬性,其 [Is Moniker Key] 選項在 [Xml Serialization Behavior] 中設定為
true
,則會使用限定索引鍵 Moniker。 在此範例中,針對領域類別 "Album" 和 "Song" 中名為 "Title" 的領域屬性設定此選項。
限定索引鍵 Moniker 比識別碼 Moniker 更容易讀取。 如果您想要讓人員讀取模型檔案的 XML,請考慮使用限定索引鍵 Moniker。 不過,使用者可以將多個元素設定為具有相同 Moniker 索引鍵。 重複的索引鍵可能會導致檔案無法正確重新載入。 因此,如果您定義使用限定索引鍵 Moniker 參考的領域類別,您應該考慮防止使用者儲存具有重複 Moniker 的檔案。
設定識別碼 Moniker 所參考的領域類別
請確定 [Is Moniker Key] 是類別及其基底類別中每個領域屬性的
false
。在 [DSL 總管] 中,展開 Xml Serialization Behavior\Class Data\<領域類別>\Element Data。
確認每個領域屬性的 [是 Moniker 索引鍵] 是
false
。如果領域類別有基底類別,請重複該類別中的程序。
為領域類別設定 Serialize Id =
true
。您可以在 [XML 序列化行為] 底下找到此屬性。
設定限定索引鍵 Moniker 所參考的領域類別
為現有領域類別的領域屬性設定 [是 Moniker 索引鍵]。 屬性的類型必須是
string
。在 [DSL 總管] 中,展開 Xml Serialization Behavior\Class Data\<領域類別>\Element Data,然後選取領域屬性。
在 [屬性] 視窗中,將 [Is Moniker Key] 設定為
true
。
- 或 -
使用具名領域類別工具建立新的領域類別。
此工具會建立名為 Name 之領域屬性的新類別。 此領域屬性的 [Is Element Name] 和 [Is Moniker Key] 屬性會初始化為
true
。- 或 -
建立從領域類別到具有 Moniker 索引鍵屬性的另一個類別的繼承關聯性。
避免重複 Moniker
如果您使用限定索引鍵 Moniker,則使用者模型中的兩個元素在索引鍵屬性中可能會有相同的值。 例如,如果您的 DSL 類別 Person 具有屬性 Name,則使用者可以將兩個元素的 Name 設定為相同。 雖然模型可以儲存至檔案,但不會正確重新載入。
有數種方法可協助避免這種情況:
為索引鍵領域屬性設定 [Is Element Name] =
true
。 選取 DSL 定義圖表上的領域屬性,然後在 [屬性] 視窗中設定值。當使用者建立類別的新執行個體時,這個值會導致領域屬性自動獲指派不同的值。 預設行為會將數字新增至類別名稱的結尾。 這不會防止使用者將名稱變更為重複的名稱,但是對於使用者在儲存模型之前未設定值的情況有幫助。
啟用 DSL 的驗證。 在 [DSL 總管] 中,選取 Editor\Validation,然後將 [Uses...] 屬性設定為
true
。有自動產生的驗證方法會檢查語意模糊。 方法位於
Load
驗證類別中。 這可確保系統會警告使用者,可能無法重新開啟檔案。如需詳細資訊,請參閱特定領域語言中的驗證。
Moniker 路徑和限定詞
限定索引鍵 Moniker 結尾為 Moniker 索引鍵,並在內嵌樹狀結構中加上其父系的 Moniker 前置詞。 例如,如果 Album 的 Moniker 為:
<albumMoniker title="/My Favorites/Jazz after Teatime" />
然後該 Album 中的其中一首 Song 是:
<songMoniker title="/My Favorites/Jazz after Teatime/Hot tea" />
不過,如果系統會改為以識別碼參考 Album,則 Moniker 會如下所示:
<albumMoniker Id="77472c3a-9bf9-4085-976a-d97a4745237c" />
<songMoniker title="/77472c3a-9bf9-4085-976a-d97a4745237c/Hot tea" />
請注意,因為 GUID 是唯一的,所以絕不會加上其父系的 Moniker 前置詞。
如果您知道特定領域屬性在模型中一律會有唯一值,您可以針對該屬性將 [Is Moniker Qualifier] 設定為 true
。 這會導致其當做限定詞使用,而不使用父系的 Moniker。 例如,如果您針對 Album 類別的 Title 領域屬性同時設定 [Is Moniker Qualifier] 和 [Is Moniker Key],則模型的名稱或識別碼不會用於 Album 及其內嵌子系的 Moniker 中:
<albumMoniker name="Jazz after Teatime" />
<songMoniker title="/Jazz after Teatime/Hot tea" />
自訂 XML 的結構
若要進行下列自訂,請展開 [DSL 總管] 中的 [Xml Serialization Behavior] 節點。 在領域類別下,展開 [Element Data] 節點,以查看來源為此類別的屬性和關聯性清單。 選取關聯性,並在 [屬性] 視窗中調整其選項。
將 [Omit Element] 設定為 true,以省略來源角色節點,僅留下目標元素的清單。 如果來源與目標類別之間有多個關聯性,則不應該設定此選項。
<familyTreeModel ...> <!-- The following node is omitted by using Omit Element: --> <!-- <people> --> <person name="Henry VIII" .../> <person name="Elizabeth I" .../> <!-- </people> --> </familyTreeModel>
設定 [Use Full Form],將目標節點內嵌在代表關聯性執行個體的節點中。 當您將領域屬性新增至領域關聯時,會自動設定此選項。
<familyTreeModel ...> <people> <!-- The following node is inserted by using Use Full Form: --> <familyTreeModelHasPeople myRelationshipProperty="x1"> <person name="Henry VIII" .../> </familyTreeModelHasPeople> <familyTreeModelHasPeople myRelationshipProperty="x2"> <person name="Elizabeth I" .../> </familyTreeModelHasPeople> </people> </familyTreeModel>
設定 [表示法] = [元素],將領域屬性儲存為元素,而不是儲存為屬性值。
<person name="Elizabeth I" birthYear="1533"> <deathYear>1603</deathYear> </person>
若要變更序列化屬性和關聯性的順序,請以滑鼠右鍵按一下 [元素資料] 底下的項目,並使用 [上移] 或 [下移] 功能表命令。
使用程式碼的主要自訂
您可以取代部分或所有序列化演算法。
建議您研究 Dsl\Generated Code\Serializer.cs 和 SerializationHelper.cs 中的程式碼。
自訂特定類別的序列化
在 [Xml Serialization Behavior] 底下該類別的節點中設定 [Is Custom]。
轉換所有範本、建置解決方案,並調查產生的編譯錯誤。 每個錯誤附近的註解會說明您必須提供的程式碼。
為整個模型提供您自己的序列化
- 覆寫 Dsl\GeneratedCode\SerializationHelper.cs 中的方法
XML 序列化行為中的選項
在 DSL 總管中,XML 序列化行為節點包含每個領域類別、關聯性、圖形、連接器和圖表類別的子節點。 在這些節點底下,是來源為該元素的屬性和關聯性清單。 關聯性會以自己的權限和來源類別來表示。
下表摘要說明您可以在 DSL 定義的這一節中設定的選項。 在每個案例中,選取 [DSL 總管] 中的元素,然後在 [屬性] 視窗中設定選項。
XML 類別資料
這些元素可在 [DSL 總管] 的 Xml Serialization Behavior\Class Data 底下找到。
屬性 | 說明 |
---|---|
Has Custom Element Schema | 如果為 True,指出領域類別有自訂元素結構描述 |
是自訂 | 如果您想要為此領域類別撰寫自己的序列化和還原序列化程式碼,請將此選項設定為 True。 建置解決方案並調查錯誤,以探索詳細指示。 |
領域類別 | 套用此類別資料節點的領域類別。 唯讀。 |
元素名稱 | 這個類別元素的 XML 節點名稱。 預設值是領域類別名稱的小寫版本。 |
Moniker Attribute Name | Moniker 元素中用來包含參考的屬性名稱。 如果空白,則會使用索引鍵屬性或識別碼的名稱。 在此範例中,它是「名稱」: <personMoniker name="/Mike Nash"/> |
Moniker Element Name | XML 元素名稱,用於參考此類別元素的 Moniker。 預設值是尾碼為「Moniker」的小寫版本類別名稱。 例如: personMoniker 。 |
Moniker Type Name | XSD 類型名稱,替此類型元素的 Moniker 所產生。 XSD 位於 Dsl\Generated Code\*Schema.xsd |
Serialize Id | 如果為 True,則元素 GUID 會包含在檔案中。 如果沒有任何屬性標示為 [Is Moniker Key],且 DSL 定義這個類別的參考關聯性,則必須為 true。 |
類型名稱 | XML 類型名稱,自指定的領域類別中的 XSD 產生。 |
備註 | 與此元素相關的非正式備註 |
Xml Property Data
XML 屬性節點位於類別節點底下。
屬性 | 說明 |
---|---|
領域屬性 | 套用 XML 序列化組態資料的屬性。 唯讀。 |
Is Moniker Key | 如果為 True,則會使用此屬性作為索引鍵,用來建立參考這個領域類別執行個體的 Moniker。 |
Is Moniker Qualifier | 若為 True,會將屬性用於建立 Moniker 中的限定詞。 如果為 false,而且如果此領域類別的 SerializeId 不是 true,Moniker 就會由內嵌樹狀結構中父元素的 Moniker 限定。 |
表示法 | 若為 Attribute,會將屬性序列化為 XML 屬性; 若為 Element,會將其序列化為元素; 若為 Ignore,則不會序列化。 |
Xml Name | 名稱,用於 XML 屬性或代表屬性的元素。 根據預設,這是領域屬性名稱的小寫版本。 |
備註 | 與此元素相關的非正式備註 |
Xml Role data
角色資料節點位於來源類別節點底下。
屬性 | 說明 |
---|---|
Has Custom Moniker | 如果您想要提供自己的程式碼來產生和解析周遊此關聯性的 Moniker,請將此屬性設定為 true。 如需詳細指示,請建置解決方案,然後按兩下錯誤訊息。 |
領域關聯 | 指定這些選項套用的關聯性。 唯讀。 |
Omit Element | 若為 True,會從結構描述中省略對應到來源角色的 XML 節點。 如果來源與目標類別之間有多個關聯性,此角色節點會區分屬於兩個關聯性的連結。 因此,建議您在此案例中不要設定此選項。 |
Role Element Name | 指定衍生自來源角色的 XML 元素名稱。 預設值是角色屬性名稱。 |
Use Full Form | 如果為 true,則每個目標元素或 Moniker 都會包含在代表關聯性的 XML 節點中。 如果關聯性有自己的領域屬性,這應該設定為 true。 |
相關內容
意見反應
https://aka.ms/ContentUserFeedback。
即將登場:在 2024 年,我們將逐步淘汰 GitHub 問題作為內容的意見反應機制,並將它取代為新的意見反應系統。 如需詳細資訊,請參閱:提交並檢視相關的意見反應