Visual Studio ModelBus 提供方法,讓您建立模型間及其他工具至模型的連結。 例如,您可以連結特定領域語言 (DSL) 模型和 UML 模型。 您可以建立一組整合的 DSL。
警告
本文所述的 Visual Studio ModelBus 延伸模組已不再提供下載。 不過,這些指示仍適用於已安裝此延伸模組的使用者。
ModelBus 可讓您建立模型或模型內特定項目的唯一參考。 這個參考可以儲存在模型外,例如儲存在另一個模型的項目中。 在此情況下,工具需要取得項目的存取權,模型匯流排基礎結構會載入適當的模型,並傳回項目。 如有需要,您可以向使用者顯示模型。 如果無法從先前的位置存取檔案,ModelBus 會請使用者尋找檔案。 如果使用者找到檔案,ModelBus 會更新該檔案的所有參考。
注意
在 ModelBus 的目前 Visual Studio 實作中,連結的模型必須是相同 Visual Studio 解決方案中的項目。
如需 ModelBus 延伸模組的詳細資訊,請參閱下列資源:
注意
文字範本轉換元件會作為 Visual Studio 延伸模組開發工作負載的一部分自動安裝。 您也可以從 Visual Studio 安裝程式的 [個別元件] 索引標籤加以安裝,其位於 [SDK、程式庫和架構] 底下。 從 [個別元件] 索引標籤安裝 [模型化 SDK] 元件。
提供 DSL 的存取權
必須先定義適用於 DSL 的 ModelBusAdapter,才能建立模型或其項目的 ModelBus 參考。 執行這項操作最簡單的方式是使用 Visual Studio ModelBus 延伸模組,其會將命令新增至 DSL 設計工具。
將 DSL 定義公開給模型匯流排
開啟 DSL 定義檔。 以滑鼠右鍵按一下設計介面,然後選取 [啟用 ModelBus]。
在對話方塊中,選擇 [我要將這個 DSL 公開給 ModelBus]。 如果您要將這個 DSL 公開給其模型,又要讓這個 DSL 使用其他 DSL 的參考,您可以選擇兩個選項。
選取 [確定]。 新專案
ModelBusAdapter
會加入至 DSL 解決方案。如果您要從文字範本存取 DSL,您必須修改新專案中的 AdapterManager.tt。 如果您要從其他程式碼 (例如命令和事件處理常式) 存取 DSL,請略過這個步驟。 如需詳細資訊,請參閱 在文字範本中使用 Visual Studio ModelBus。
將
AdapterManagerBase
的基底類別變更為 VsTextTemplatingModelingAdapterManager。在接近檔案結尾處,將此屬性插入到類別
AdapterManager
的前面:[Microsoft.VisualStudio.Modeling.Integration.HostSpecific(HostName)]
在
ModelBusAdapter
專案的 NuGet 套件管理員中,將 NuGet PackageReference 新增至Microsoft.VisualStudio.TextTemplating.Modeling
。如果您要同時能夠從文字範本和其他程式碼存取 DSL,您需要一個已修改的配接器和一個未修改的配接器。
選取 [轉換所有範本]。
重建方案。
ModelBus 現在可以開啟此 DSL 的執行個體。
資料夾 ModelBusAdapters\bin* 包含
Dsl
專案和ModelBusAdapters
專案建置的組件。 若要從另一個 DSL 參考這個 DSL,請匯入這些組件。
確定可參考元素
Visual Studio ModelBus 配接器預設會使用元素的 GUID 來識別。 這些識別碼必須保存在模型檔案中。
確定保存元素識別碼:
開啟 DslDefinition.dsl。
在 [DSL 總管] 中,依序展開 [XML 序列化行為] 和 [類別資料]。
對於您要建立 ModelBus 參考的每個類別:
選取類別節點,然後在 [屬性] 視窗中,確定 [序列化識別碼] 已設定為
true
。
或者,如果您要使用元素名稱 (而不是 GUID) 來識別元素,您可以覆寫產生之配接器的組件。 覆寫配接器類別中的下列方法:
- 覆寫
GetElementId
以傳回您要使用的 ID。 建立參考時,會呼叫這個方法。 - 覆寫
ResolveElementReference
,以從 ModelBus 參考中找到正確元素。
從另一個 DSL 存取某個 DSL
您可以在 DSL 的網域屬性中儲存 ModelBus 參考,以及撰寫自訂程式碼來使用這些參考。 您也可以讓使用者選擇模型檔案和模型內的某個元素,藉此建立 ModelBus 參考。
若要允許 DSL 使用另一個 DSL 的參考,您應該先將該 DSL 設定為模型匯流排參考的取用者。
允許 DSL 使用已公開 DSL 的參考
在 [DSL 定義] 圖表中,以滑鼠右鍵按一下圖表的主要部分,然後選取 [啟用 ModelBus]。
在對話方塊中,選取 [我要讓這個模型使用模型匯流排參考]。
在取用 DSL 的
Dsl
專案中,將下列組件新增至專案參考。 這些組件 (.dll 檔案) 位於公開 DSL 的 ModelBusAdapter\bin\* 目錄中。公開的 DSL 組件,例如 Fabrikam.FamilyTree.Dsl.dll
公開的模型匯流排配接器組件,例如 Fabrikam.FamilyTree.ModelBusAdapter.dll
將下列 .NET 組件加入至使用 DSL 專案的專案參考。
- Microsoft.VisualStudio.Modeling.Sdk.Integration.dll
- Microsoft.VisualStudio.Modeling.Sdk.Integration.Shell.dll
在網域屬性中儲存 ModelBusReference
在使用 DSL 的 DSL 定義中,將網域屬性加入至網域類別並設定其名稱。
在已選取網域屬性的 [屬性] 視窗中,將 [類型] 設定為
ModelBusReference
。在這個階段,程式碼可以設定屬性值。 值在 [屬性] 視窗中是唯讀的。
您可以允許使用者使用專用 ModelBusReference 編輯器來設定此屬性。 此編輯器或選擇器有兩種版本。 其中一個版本允許使用者選擇模型檔,另一個版本允許使用者選擇模型檔和模型內的某個項目。
允許使用者設定網域屬性中的 ModelBusReference
以滑鼠右鍵按一下網域屬性,然後選取 [編輯 ModelBusReference 特定屬性]。 [模型匯流排選擇器] 對話方塊隨即開啟。
針對模型或模型內的某個元素設定適當的 [ModelBusReference 類型]。
在檔案對話方塊篩選字串中,輸入字串 (例如
Family Tree files |*.ftree
)。 替代已公開 DSL 的副檔名。如果您選擇模型內某個項目的參考,您可以加入使用者可選取的類型清單,例如
Company.FamilyTree.Person
。選取 [確定],然後選取 [方案總管] 工具列中的 [轉換所有範本]。
警告
如果您尚未選取有效的模型或實體,[確定] 按鈕即使可能顯示為已啟用,也不會有任何作用。
如果您指定目標類型清單 (例如
Company.FamilyTree.Person
),則必須將組件參考加入至您的 DSL 專案,並參考目標 DSL 的 DLL,例如 Company.FamilyTree.Dsl.dll。
測試 ModelBusReference
建置已公開的 DSL 和使用 DSL。
按 F5 鍵或 CTRL+F5,在實驗模式中執行其中一個 DSL。
在 Visual Studio 之實驗執行個體的偵錯專案中,加入每個 DSL 執行個體的檔案。
注意
只有在模型是相同 Visual Studio 解決方案中的項目時,Visual Studio ModelBus 才能解析這些模型的參考。 例如,您無法建立針對檔案系統其他部分之模型檔的參考。
在已公開的 DSL 執行個體中建立一些項目和連結,並加以儲存。
開啟使用 DSL 的執行個體,然後選取具有模型匯流排參考屬性的模型項目。
在 [屬性] 視窗中,按兩下模型匯流排參考屬性。 選擇器對話方塊隨即開啟。
選取 [瀏覽],然後選取已公開 DSL 的執行個體。
如果已指定特定元素的模型匯流排參考,選擇器也可讓您選擇模型內的某個項目。
在程式碼中建立參考
當您要儲存模型或模型內某個元素的參考時,請建立 ModelBusReference
。 ModelBusReference
的類型有兩種:模型參考和項目參考。
若要建立模型參考,您需要其模型為執行個體之 DSL 的 AdapterManager,以及模型的檔案名稱或 Visual Studio 專案項目。
若要建立項目參考,您需要模型檔的配接器,以及所要參考的項目。
注意
透過 Visual Studio ModelBus,您可以建立僅針對相同 Visual Studio 解決方案中之項目的參考。
匯入已公開的 DSL 組件
在使用專案中,將專案參考新增至 DSL 和已公開 DSL 的 ModelBusAdapter
組件。
例如,假設您要在 MusicLibrary DSL 的元素中儲存 ModelBus 參考。 ModelBus 參考會參考 FamilyTree DSL 的元素。 在 MusicLibrary 解決方案中 Dsl
專案的 [參考] 節點中,將參考新增至下列組件:
Fabrikam.FamilyTree.Dsl.dll。 公開的 DSL。
Fabrikam.FamilyTree.ModelBusAdapters.dll 已公開 DSL 的 ModelBus 配接器。
Microsoft.VisualStudio.Modeling.Sdk.Integration
Microsoft.VisualStudio.Modeling.Sdk.Integration.Shell
您可以在已公開 DSL 的
ModelBusAdapters
專案中找到這些組件 (位於 *bin\**)。在要建立參考的程式碼檔案中,您通常必須匯入這些命名空間:
// The namespace of the DSL you want to reference:
using Fabrikam.FamilyTree; // Exposed DSL
using Fabrikam.FamilyTree.ModelBusAdapters;
using Microsoft.VisualStudio.Modeling.Integration;
using System.Linq;
...
建立模型的參考
若要建立模型參考,您可以存取已公開 DSL 的 AdapterManager,然後使用 AdapterManager 來建立模型的參考。 您可以指定檔案路徑,或 EnvDTE.ProjectItem
。
您可以從 AdapterManager 取得配接器,以提供模型內個別項目的存取權。
注意
您必須在配接器使用完畢之後加以處置。 使用 using
陳述式是達成此目標的最便利方式。 說明如下例。
// The file path of a model instance of the FamilyTree DSL:
string targetModelFile = "TudorFamilyTree.ftree";
// Get the ModelBus service:
IModelBus modelBus =
this.Store.GetService(typeof(SModelBus)) as IModelBus;
// Get an adapterManager for the target DSL:
FamilyTreeAdapterManager manager =
(modelbus.GetAdapterManager(FamilyTreeAdapter.AdapterId)
as FamilyTreeAdapterManager;
// or: (modelBus.FindAdapterManagers(targetModelFile).First())
// or could provide an EnvDTE.ProjectItem
// Create a reference to the target model:
// NOTE: the target model must be a file in this project.
ModelBusReference modelReference =
manager.CreateReference(targetModelFile);
// or can use an EnvDTE.ProjectItem instead of the filename
// Get the root element of this model:
using (FamilyTreeAdapter adapter =
modelBus.CreateAdapter(modelReference) as FamilyTreeAdapter)
{
FamilyTree modelRoot = adapter.ModelRoot;
// Access elements under the root in the usual way:
foreach (Person p in modelRoot.Persons) {...}
// You can create adapters for individual elements:
ModelBusReference elementReference =
adapter.GetElementReference(person);
...
} // Dispose adapter
如果您想在稍後能夠使用 modelReference
,您可以將其儲存在具有外部類型 ModelBusReference
的網域屬性中:
using Transaction t = this.Store.TransactionManager
.BeginTransaction("keep reference"))
{
artist.FamilyTreeReference = modelReference;
t.Commit();
}
若要允許使用者編輯這個網域屬性,請使用 ModelReferenceEditor
做為 Editor
屬性中的參數。 如需詳細資訊,請參閱允許使用者編輯參考。
建立項目的參考
您針對模型建立的配接器可用來建立及解析參考。
// person is an element in the FamilyTree model:
ModelBusReference personReference =
adapter.GetElementReference(person);
如果您想在稍後能夠使用 elementReference
,您可以將其儲存在具有外部類型 ModelBusReference
的網域屬性中。 若要允許使用者進行編輯,請使用 ModelElementReferenceEditor
做為 Editor
屬性中的參數。 如需詳細資訊,請參閱允許使用者編輯參考。
解析參考
如果您具有 ModelBusReference
(MBR),您可以取得其參考的模型或模型項目。 如果圖表或其他檢視上顯示此項目,您可以開啟檢視並選取此項目。
您可以從 MBR 建立配接器。 您可以從配接器取得模型根。 您也可以解析參考模型內特定項目的 MBR。
using Microsoft.VisualStudio.Modeling.Integration; ...
ModelBusReference elementReference = ...;
// Get the ModelBus service:
IModelBus modelBus =
this.Store.GetService(typeof(SModelBus)) as IModelBus;
// Use a model reference or an element reference
// to obtain an adapter for the target model:
using (FamilyTreeAdapter adapter =
modelBus.CreateAdapter(elementReference) as FamilyTreeAdapter)
// or CreateAdapter(modelReference)
{
// Get the root of the model:
FamilyTree tree = adapter.ModelRoot;
// Get a model element:
MyDomainClass mel =
adapter.ResolveElementReference<MyDomainClass>(elementReference);
if (mel != null) {...}
// Get the diagram or other view, if there is one:
ModelBusView view = adapter.GetDefaultView();
if (view != null)
{
view.Open();
// Display the diagram:
view.Show();
// Attempt to select the shape that presents the element:
view.SetSelection(elementReference);
}
} // Dispose the adapter.
解析文字範本中的 ModelBusReferences
您要存取的 DSL 必須具有已設定供文字範本存取的 ModelBus 配接器。 如需詳細資訊,請參閱 提供 DSL 的存取權。
一般而言,您會使用儲存在來源 DSL 中的模型匯流排參考 (MBR) 來存取目標 DSL。 因此,您的範本會包含來源 DSL 的指示詞,以及用於解析 MBR 的程式碼。 如需文字範本的詳細資訊,請參閱從特定領域語言產生程式碼。
<#@ template debug="true" hostspecific="true"
inherits="Microsoft.VisualStudio.TextTemplating.Modeling.ModelBusEnabledTextTransformation" #>
<#@ SourceDsl processor="SourceDslDirectiveProcessor" requires="fileName='Sample.source'" #>
<#@ output extension=".txt" #>
<#@ assembly name = "Microsoft.VisualStudio.Modeling.Sdk.Integration.11.0" #>
<#@ assembly name = "System.Core" #>
<#@ assembly name = "Company.CompartmentDragDrop.Dsl.dll" #>
<#@ assembly name = "Company.CompartmentDragDrop.ModelBusAdapter.dll" #>
<#@ import namespace="Microsoft.VisualStudio.Modeling.Integration" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="Company.CompartmentDragDrop" #>
<#@ import namespace="Company.CompartmentDragDrop.ModelBusAdapters" #>
<# // Get source root from directive processor:
ExampleModel source = this.ExampleModel;
// This DSL has an MBR in its root:
using (ModelBusAdapter adapter = this.ModelBus.CreateAdapter(source.ModelReference) as ModelBusAdapter)
{
ModelBusAdapterManager manager = this.ModelBus.FindAdapterManagers(this.Host.ResolvePath("Sample.compDD1")).FirstOrDefault();
ModelBusReference modelReference =
manager.CreateReference(this.Host.ResolvePath("Sample.compDD1"));
// Get the root element of this model:
using (CompartmentDragDropAdapter adapter =
this.ModelBus.CreateAdapter(modelReference) as CompartmentDragDropAdapter)
{
ModelRoot root = adapter.ModelRoot;
#>
[[<#= root.Name #>]]
<#
}
#>
如需詳細資訊和逐步解說,請參閱在文字範本中使用 Visual Studio ModelBus。
序列化 ModelBusReference
如果您要以字串格式儲存 ModelBusReference
(MBR),您可以加以序列化:
string serialized = modelBus.SerializeReference(elementReference);
// Store it anywhere, then get it back again:
ModelBusReference elementReferenceRestored =
modelBus.DeserializeReference(serialized, null);
以此方式序列化的 MBR 不會影響內容。 如果您使用簡單檔案架構的模型匯流排配接器,MBR 會包含絕對檔案路徑。 如果執行個體模型檔案永遠不會移動,此序列化便已足夠。 不過,模型檔案通常是 Visual Studio 專案中的項目。 您的使用者必須能夠將整個專案移至檔案系統的不同部分。 使用者也必須能夠控制專案的原始檔,並在不同的電腦上開啟專案。 因此,檔案名稱應相對於包含檔案之專案的位置來進行序列化。
相對於指定的檔案路徑來進行序列化
ModelBusReference
包含 ReferenceContext
,這是您可以儲存資訊 (例如要序列化的相對檔案路徑) 的字典。
若要相對於路徑進行序列化:
elementReference.ReferenceContext.Add(
ModelBusReferencePropertySerializer.FilePathSaveContextKey,
currentProjectFilePath);
string serialized = modelBus.SerializeReference(elementReference);
若要從字串擷取參考:
ReferenceContext context = new ReferenceContext();
context.Add(ModelBusReferencePropertySerializer.FilePathLoadContextKey,
currentProjectFilePath);
ModelBusReference elementReferenceRestored =
modelBus.DeserializeReference(serialized, context);
其他配接器建立的 ModelBusReferences
如果您要建立自己的配接器,下列資訊會很實用。
ModelBusReference
(MBR) 是由兩個組件所組成:由模型匯流排還原序列化的 MBR 標頭,以及特定配接器管理員處理的特定配接器。 此方法可讓您提供自己的配接器序列化格式。 例如,您可以參考資料庫而不是檔案,或者您可以在配接器參考中儲存其他資訊。 您所擁有的配接器會在 ReferenceContext
中放置其他資訊。
當您還原序列化 MBR 時,您必須提供 ReferenceContext,然後再將其儲存在 MBR 物件中。 當您序列化 MBR 時,配接器會使用儲存的 ReferenceContext 協助產生字串。 還原序列化的字串不包含 ReferenceContext 中的所有資訊。 例如,在簡單檔案架構的配接器中,ReferenceContext 包含根檔案路徑。 此路徑不會儲存在序列化的 MBR 字串中。
MBR 的還原序列化作業可分為兩個階段:
ModelBusReferencePropertySerializer
是處理 MBR 標頭的標準序列化程式。 它使用標準 DSLSerializationContext
屬性封包,該封包使用ReferenceContext
索引鍵儲存在ModelBusReferencePropertySerializer.ModelBusLoadContextKey
中。 特別要提的是,SerializationContext
應包含ModelBus
的執行個體。您的 ModelBus 配接器處理配接器特有的 MBR 部分。 它可以使用儲存在 MBR 之 ReferenceContext 中的其他資訊。 簡單檔案架構的配接器使用下列索引鍵來保存根檔案路徑:
FilePathLoadContextKey
和FilePathSaveContextKey
。模型檔案中的配接器參考只有在使用時才可還原序列化。
建立模型
建立、開啟及編輯模型
下列程式碼片段取自 VMSDK 網站上的「狀態機器」範例。 此程式碼片段描述如何使用 ModelBusReferences 建立及開啟模型,以及取得與模型相關聯的圖表。
在這個範例中,目標 DSL 的名稱為 StateMachine。 數個名稱會衍生自此名稱,例如模型類別的名稱和 ModelBusAdapter 的名稱。
using Fabrikam.StateMachine.ModelBusAdapters;
using Microsoft.VisualStudio.Modeling;
using Microsoft.VisualStudio.Modeling.Diagrams;
using Microsoft.VisualStudio.Modeling.Integration;
using Microsoft.VisualStudio.Modeling.Integration.Shell;
using Microsoft.VisualStudio.Modeling.Shell;
...
// Create a new model.
ModelBusReference modelReference =
StateMachineAdapterManager .CreateStateMachineModel(modelName, fileName);
//Keep reference of new model in this model.
using (Transaction t = ...)
{
myModelElement.ReferenceProperty = modelReference;
t.Commit();
}
// Get the ModelBus service from Visual Studio.
IModelBus modelBus = Microsoft.VisualStudio.Shell.Package.
GetGlobalService(typeof(SModelBus)) as IModelBus;
// Get a modelbus adapter on the new model.
ModelBusAdapter modelBusAdapter;
modelBus.TryCreateAdapter(modelReference,
this.ServiceProvider, out modelBusAdapter);
using (StateMachineAdapter adapter =
modelBusAdapter as StateMachineAdapter)
{
if (adapter != null)
{
// Obtain a Diagram from the adapter.
Diagram targetDiagram =
((StandardVsModelingDiagramView)
adapter.GetDefaultView()
).Diagram;
using (Transaction t =
targetDiagram.Store.TransactionManager
.BeginTransaction("Update diagram"))
{
DoUpdates(targetDiagram);
t.Commit();
}
// Display the new diagram.
adapter.GetDefaultView().Show();
}
}
驗證參考
BrokenReferenceDetector 會測試存放區中所有可儲存 ModelBusReferences 的網域屬性。 它會在找到您提供的任何動作時,呼叫此動作。 此測試對驗證方法很有用。 下列驗證方法會在嘗試儲存模型時測試存放區,並在錯誤視窗中報告不完整的參考:
[ValidationMethod(ValidationCategories.Save)]
public void ValidateModelBusReferences(ValidationContext context)
{
BrokenReferenceDetector.DetectBrokenReferences(this.Store,
delegate(ModelElement element, // parent of property
DomainPropertyInfo property, // identifies property
ModelBusReference reference) // invalid reference
{
context.LogError(string.Format(INVALID_REF_FORMAT,
property.Name,
referenceState.Name,
new ModelBusReferenceTypeConverter().
ConvertToInvariantString(reference)),
"Reference",
element);
});
}
private const string INVALID_REF_FORMAT =
"The '{0}' domain property of this ReferenceState instance "
+ "named '{1}' contains reference value '{2}' which is invalid";
ModelBus 擴充功能執行的動作
如果您要擴充使用 ModelBus,這些資訊可能會很實用。
ModelBus 擴充功能在 DSL 方案中進行了下列變更。
當您以滑鼠右鍵按一下 DSL 定義圖表,選取 [啟用 ModelBus],然後選取 [啟用這個 DSL 以使用 ModelBus] 時:
在 DSL 專案中,應該將參考新增至 Microsoft.VisualStudio.Modeling.Sdk.Integration.dll。
在 DSL 定義中,會加入外部類型參考:
Microsoft.VisualStudio.Modeling.Integration.ModelBusReference
。您可以在 [DSL 總管] 的 [網域類型] 下看到這個參考。 若要手動加入外部類型參考,請以滑鼠右鍵按一下根節點。
已新增範本檔案,Dsl\GeneratedCode\ModelBusReferencesSerialization.tt。
當您將網域屬性的類型設定為 ModelBusReference,然後以滑鼠右鍵按一下屬性,並選取 [啟用 ModelBusReference 的特定屬性] 時:
數個 CLR 屬性會加入至網域屬性。 您會在 [屬性] 視窗的 [自訂屬性] 欄位中看到這些屬性。 在 Dsl\GeneratedCode\DomainClasses.cs 中,您可以看到屬性宣告上的屬性:
[System.ComponentModel.TypeConverter(typeof( Microsoft.VisualStudio.Modeling.Integration.ModelBusReferenceTypeConverter))] [System.ComponentModel.Editor(typeof( Microsoft.VisualStudio.Modeling.Integration.Picker .ModelReferenceEditor // or ModelElementReferenceEditor ), typeof(System.Drawing.Design.UITypeEditor))] [Microsoft.VisualStudio.Modeling.Integration.Picker .SupplyFileBasedBrowserConfiguration ("Choose a model file", "Target model|*.target")]
當您以滑鼠右鍵按一下 [DSL 定義圖表],選取 [啟用 ModelBus],然後選取 [將這個 DSL 公開給 ModelBus] 時:
新專案
ModelBusAdapter
會加入至方案。ModelBusAdapter
的參考會加入至DslPackage
專案。ModelBusAdapter
會參考Dsl
專案。在 DslPackage\source.extention.tt 中,
|ModelBusAdapter|
會新增為 MEF 元件。