共用方式為


自訂檔案儲存體和 XML 序列化

當使用者在 Visual Studio 中儲存特定領域語言 (DSL) 的執行個體或模型時,就會建立或更新 XML 檔案。 檔案可以重新載入以在市集中重新建立模型。

您可以藉由在 DSL 總管中的 XML 序列化行為下調整設定,自訂序列化配置。 每個領域類別、屬性和關聯性在 XML 序列化行為底下都有節點。 關聯性位於其來源類別底下。 也有對應至圖形、連接器和圖表類別的節點。

您也可以撰寫程式碼以進行更進階的自訂。

注意

如果您想要以特定格式儲存模型,但不需要從該表單重新載入模型,請考慮使用文字範本從模型產生輸出,而不是自訂序列化配置。 如需詳細資訊,請參閱從特定領域語言產生程式碼

模型和圖表檔案

每個模型通常會儲存在兩個檔案中:

  • 模型檔案具有例如 Model1.mydsl 的名稱。 會儲存模型元素和關聯性及其屬性。 .mydsl 之類的副檔名是由 DSL 定義中編輯器節點的 FileExtension 屬性所決定。

  • 圖表檔案具有例如 Model1.mydsl.diagram 的名稱。 會儲存圖形、連接器及其位置、色彩、線條粗細,以及圖表外觀的其他詳細資料。 如果使用者刪除 .diagram 檔案,模型中的基本資訊不會遺失。 只有圖表配置會遺失。 開啟模型檔案時,將會建立一組預設的圖形和連接器。

變更 DSL 副檔名

  1. 開啟 DSL 定義。 在 [DSL 總管] 中,按一下 [編輯器] 節點。

  2. 在 [屬性] 視窗中,編輯 FileExtension 屬性。 不包含副檔名的初始 "."。

  3. 在 [方案總管] 中,變更 DslPackage\ProjectItemTemplates 中兩個項目範本檔案的名稱。 這些檔案具有遵循以下格式的名稱:

    myDsl.diagram

    myDsl.myDsl

預設序列化配置

為了建立此主題的範例,使用了下列 DSL 定義。

DSL Definition diagram - family tree model

此 DSL 是用來建立在螢幕上具有下列外觀的模型。

Family tree diagram, toolbox, and explorer

此模型已儲存,然後在 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 節點都具有與領域類別名稱相同的名稱,但是初始字母為小寫。 例如,familyTreeModelperson

  • 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 所參考的領域類別

  1. 請確定 [Is Moniker Key] 是類別及其基底類別中每個領域屬性的 false

    1. 在 [DSL 總管] 中,展開 Xml Serialization Behavior\Class Data\<領域類別>\Element Data

    2. 確認每個領域屬性的 [是 Moniker 索引鍵]false

    3. 如果領域類別有基底類別,請重複該類別中的程序。

  2. 為領域類別設定 Serialize Id = true

    您可以在 [XML 序列化行為] 底下找到此屬性。

設定限定索引鍵 Moniker 所參考的領域類別

  • 為現有領域類別的領域屬性設定 [是 Moniker 索引鍵]。 屬性的類型必須是 string

    1. 在 [DSL 總管] 中,展開 Xml Serialization Behavior\Class Data\<領域類別>\Element Data,然後選取領域屬性。

    2. 在 [屬性] 視窗中,將 [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.csSerializationHelper.cs 中的程式碼。

自訂特定類別的序列化

  1. 在 [Xml Serialization Behavior] 底下該類別的節點中設定 [Is Custom]

  2. 轉換所有範本、建置解決方案,並調查產生的編譯錯誤。 每個錯誤附近的註解會說明您必須提供的程式碼。

為整個模型提供您自己的序列化

  1. 覆寫 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。