共用方式為


使用 MEF 擴充您的 DSL

您可以 exntend 您定義域專屬語言 (DSL) 使用管理擴充性架構 (MEF)。您或其他程式開發人員能夠撰寫 DSL 的擴充功能,而不會變更 DSL 定義和程式碼。這些延伸包括功能表命令、 拖放處理常式和驗證。使用者可以安裝您的 DSL 並選擇性地安裝延伸它。

另外,當您在 [您的 DSL 啟用 MEF,它能方便您撰寫的一些功能,您的 DSL 的即使全部整合 DSL 與它們。

如需 MEF 的詳細資訊,請參閱 Managed Extensibility Framework (MEF)

若要啟用您的 DSL 由 MEF 擴充

  1. 建立新的資料夾,名為MefExtensionDslPackage專案。將下列檔案:

    檔案名稱

    檔案內容

    CommandExtensionVSCT.tt

    重要事項重要事項
    設定這個 GUID CommandSetId DslPackage\GeneratedCode\Constants.tt 中所定義相同的檔案中的 GUID
    <#@ Dsl processor="DslDirectiveProcessor" requires="fileName='..\..\Dsl\DslDefinition.dsl'" #>
    <#
    // CmdSet Guid must be defined before master template is included
    // This Guid must be kept synchronized with the CommandSetId Guid in Constants.tt
    Guid guidCmdSet = new Guid ("00000000-0000-0000-0000-000000000000");
    string menuidCommandsExtensionBaseId="0x4000";
    #>
    <#@ include file="DslPackage\CommandExtensionVSCT.tt" #>

    CommandExtensionRegistrar.tt

    <#@ Dsl processor="DslDirectiveProcessor" requires="fileName='..\..\Dsl\DslDefinition.dsl'" #>
    <#@ include file="DslPackage\CommandExtensionRegistrar.tt" #>

    ValidationExtensionEnablement.tt

    <#@ Dsl processor="DslDirectiveProcessor" requires="fileName='..\..\Dsl\DslDefinition.dsl'" #>
    <#@ include file="DslPackage\ValidationExtensionEnablement.tt" #>

    ValidationExtensionRegistrar.tt

    如果您將這個檔案,您必須啟用您的 DSL 的驗證使用中的交換器,至少一個 Editor\Validation DSL 總管] 中。

    <#@ Dsl processor="DslDirectiveProcessor" requires="fileName='..\..\Dsl\DslDefinition.dsl'" #>
    <#@ include file="DslPackage\ValidationExtensionRegistrar.tt" #>

    PackageExtensionEnablement.tt

    <#@ Dsl processor="DslDirectiveProcessor" requires="fileName='..\..\Dsl\DslDefinition.dsl'" #>
    <#@ include file="DslPackage\PackageExtensionEnablement.tt" #>
  2. 建立新的資料夾,名為MefExtensionDsl專案。將下列檔案:

    檔案名稱

    內容

    DesignerExtensionMetaDataAttribute.tt

    <#@ Dsl processor="DslDirectiveProcessor" requires="fileName='..\..\Dsl\DslDefinition.dsl'" #>
    <#@ include file="Dsl\DesignerExtensionMetadataAttribute.tt" #>

    GestureExtensionEnablement.tt

    <#@ Dsl processor="DslDirectiveProcessor" requires="fileName='..\..\Dsl\DslDefinition.dsl'" #>
    <#@ include file="Dsl\GestureExtensionEnablement.tt" #>

    GestureExtensionController.tt

    <#@ Dsl processor="DslDirectiveProcessor" requires="fileName='..\..\Dsl\DslDefinition.dsl'" #>
    <#@ include file="Dsl\GestureExtensionController.tt" #>
  3. 將下面這一行加入至現有的檔案,名為DslPackage\Commands.vsct

    <Include href="MefExtension\CommandExtensionVSCT.vsct"/>
    

    插入行之後的<Include>指示詞。

  4. 開啟 [DslDefinition.dsl]。

  5. 在 DSL 總管] 中,選取 Editor\Validation

  6. 在 [屬性] 視窗中,請確定至少其中一個屬性名稱為使用... is true.

  7. 在 [方案總管] 工具列上,按一下 轉換所有的範本

    附帶的檔案會出現下每一個您所加入的檔案。

  8. 建置並執行方案以確認它仍運作。

您的 DSL 現在是 MEF 功能。您可以將功能表命令、 筆勢的處理常式,以及驗證條件約束寫成 MEF 副檔名。您可以撰寫這些擴充功能在您的 DSL 方案,以及與其他自訂的程式碼。此外,您或其他程式開發人員可以撰寫另一個Visual Studio擴充您的 DSL 的擴充功能。

正在建立的 MEF 啟用的 DSL 的延伸模組

如果您有存取權 MEF 啟用的 DSL 自己或其他人所建立的您可以撰寫延伸它。擴充功能可用來新增功能表指令、 筆勢的處理常式或驗證條件約束。若要撰寫這些擴充功能,請使用Visual Studio的副檔名 (VSIX) 解決方案。方案之中擁有兩個部分: 類別庫專案建置的程式碼的組件,並封裝組件的 VSIX 專案。

若要建立副檔名為 DSL VSIX

  1. 建立新的類別庫專案。若要這樣做,請在新的專案 對話方塊中,選取 Visual Basic視覺 C# 綴恁寁類別程式庫

  2. 在新的類別庫專案加入 DSL 的組件的參考。

    • 這個組件通常會有一個名稱結尾為"。Dsl.dll"。

    • 如果您有存取權的 DSL 專案,您可以找到組件檔名的目錄Dsl\bin\*

    • 如果您取得 DSL VSIX 檔案,您可以將 VSIX 檔案的副檔名變更為 「.zip 」 來找出組件。解壓縮.zip 檔。

  3. 加入下列 .NET 組件的參考:

    • Microsoft.VisualStudio.Modeling.Sdk.11.0.dll

    • Microsoft.VisualStudio.Modeling.Sdk.Diagrams.11.0.dll

    • Microsoft.VisualStudio.Modeling.Sdk.Shell.11.0.dll

    • System.ComponentModel.Composition.dll

    • System.Windows.Forms.dll

  4. 在 VSIX 專案中建立相同的方案。若要這樣做,請在新的專案 對話方塊方塊中,展開 Visual Basic視覺 C#,按一下 [ 擴充性,綴恁寁 VSIX 專案

  5. 在方案總管] 中,以滑鼠右鍵按一下 VSIX 專案,然後按一下設定為啟始專案

  6. 在新的專案中,開啟source.extension.vsixmanifest

  7. 按一下 [加入內容]。在對話方塊中,設定內容類型MEF 元件,和 來源專案到您的類別庫專案。

  8. 加入 DSL 的 VSIX 參考。

    1. source.extension.vsixmanifest,按一下 [ 加入參考

    2. 在對話方塊中,按一下 [ 新增承載 ,然後找出 DSL 的 VSIX 檔案。在建置在 DSL 解決方案中,VSIX 檔案DslPackage\bin\*

      這可讓使用者同時安裝 DSL 和擴充功能。如果使用者已經有安裝 DSL,將會安裝您的擴充。

  9. 檢閱並更新的其他欄位的source.extension.vsixmanifest。按一下 [ 選取版本並確認正確的Visual Studio設定版本。

  10. 類別庫專案中加入程式碼。使用下一節的範例,做為指引。

    您可以新增任何數量的命令、 鍵筆勢和驗證類別。

  11. 若要測試的副檔名,請按 F5。實驗性的執行個體中Visual Studio、 建立或開啟範例檔案的 DSL。

為 Dsl 撰寫 MEF 延伸模組

您可以撰寫擴充功能組件程式碼專案中的不同的 DSL 擴充解決方案。您也可以在 DslPackage 專案中,使用 MEF,以方便您撰寫 DSL 的一部分的命令、 筆勢及驗證程式碼。

Ff972471.collapse_all(zh-tw,VS.110).gif功能表命令

若要功能表指令,請定義一個類別,實作ICommandExtension和前置詞的類別與屬性定義於您的 DSL,名為 YourDslCommandExtension。您可以撰寫多個功能表命令的類別。

QueryStatus()每當使用者以滑鼠右鍵按一下圖表,會呼叫。它應該檢查目前的選取範圍,並設定command.Enabled指出命令適用。

using System.ComponentModel.Composition;
using System.Linq;
using Company.MyDsl; // My DSL
using Company.MyDsl.ExtensionEnablement; // My DSL
using Microsoft.VisualStudio.Modeling; // Transactions
using Microsoft.VisualStudio.Modeling.Diagrams.ExtensionEnablement; // IVsSelectionContext
using Microsoft.VisualStudio.Modeling.ExtensionEnablement; // ICommandExtension

namespace MyMefExtension
{
  // Defined in Dsl\MefExtension\DesignerExtensionMetaDataAttribute.cs:
  [MyDslCommandExtension] 
  public class MyCommandClass : ICommandExtension
  { 
    /// <summary>
    /// Provides access to current document and selection.
    /// </summary>
    [Import]
    IVsSelectionContext SelectionContext { get; set; }

    /// <summary>
    /// Called when the user selects this command.
    /// </summary>
    /// <param name="command"></param>
    public void Execute(IMenuCommand command)
    {
      // Transaction is required if you want to update elements.
      using (Transaction t = SelectionContext.CurrentStore
              .TransactionManager.BeginTransaction("fix names"))
      {
        foreach (ExampleShape shape in SelectionContext.CurrentSelection)
        {
          ExampleElement element = shape.ModelElement as ExampleElement;
          element.Name = element.Name + " !";
        }
        t.Commit();
      }
    }

    /// <summary>
    /// Called when the user right-clicks the diagram.
    /// Determines whether the command should appear.
    /// This method should set command.Enabled and command.Visible.
    /// </summary>
    /// <param name="command"></param>
    public void QueryStatus(IMenuCommand command)
    {
      command.Enabled =
        command.Visible = (SelectionContext.CurrentSelection.OfType<ExampleShape>().Count() > 0);
    }

    /// <summary>
    /// Called when the user right-clicks the diagram.
    /// Determines the text of the command in the menu.
    /// </summary>
    public string Text
    {
      get { return "My menu command"; }
    }
  }
}

Ff972471.collapse_all(zh-tw,VS.110).gif筆勢的處理常式

筆勢的處理常式可以處理物件的內部或外部從任何地方,拖曳到圖表上Visual Studio。下列範例會讓使用者從 Windows 檔案總管將檔案拖曳至圖表上。它會建立包含檔名的項目。

您可以撰寫處理常式來處理來自其他 DSL 模型和 UML 模型的拖曳。如需詳細資訊,請參閱 HOW TO:加入拖放處理常式

using System.ComponentModel.Composition;
using System.Linq;
using Company.MyDsl;
using Company.MyDsl.ExtensionEnablement;
using Microsoft.VisualStudio.Modeling; // Transactions
using Microsoft.VisualStudio.Modeling.Diagrams;
using Microsoft.VisualStudio.Modeling.Diagrams.ExtensionEnablement; 
using Microsoft.VisualStudio.Modeling.ExtensionEnablement; 

namespace MefExtension
{
  [MyDslGestureExtension]
  class MyGestureExtension : IGestureExtension
  {
    public void OnDoubleClick(ShapeElement targetElement, DiagramPointEventArgs diagramPointEventArgs)
    {
      System.Windows.Forms.MessageBox.Show("double click!");
    }
    
    /// <summary>
    /// Called when the user drags anything over the diagram.
    /// Return true if the dragged object can be dropped on the current target.
    /// </summary>
    /// <param name="targetMergeElement">The shape or diagram that the mouse is currently over</param>
    /// <param name="diagramDragEventArgs">Data about the dragged element.</param>
    /// <returns></returns>
    public bool CanDragDrop(ShapeElement targetMergeElement, DiagramDragEventArgs diagramDragEventArgs)
    {
      // This handler only allows items to be dropped onto the diagram:
      return targetMergeElement is MefDsl2Diagram &&
      // And only accepts files dragged from Windows Explorer:
        diagramDragEventArgs.Data.GetFormats().Contains("FileNameW");
    }


    /// <summary>
    /// Called when the user drops an item onto the diagram.
    /// </summary>
    /// <param name="targetDropElement"></param>
    /// <param name="diagramDragEventArgs"></param>
    public void OnDragDrop(ShapeElement targetDropElement, DiagramDragEventArgs diagramDragEventArgs)
    {
      MefDsl2Diagram diagram = targetDropElement as MefDsl2Diagram;
      if (diagram == null) return;

      // This handler only accepts files dragged from Windows Explorer:
      string[] draggedFileNames = diagramDragEventArgs.Data.GetData("FileNameW") as string[];
      if (draggedFileNames == null || draggedFileNames.Length == 0) return; 

      using (Transaction t = diagram.Store.TransactionManager.BeginTransaction("file names"))
      {
        // Create an element to represent each file:
        foreach (string fileName in draggedFileNames)
        {
          ExampleElement element = new ExampleElement(diagram.ModelElement.Partition);
          element.Name = fileName;

          // This method of adding the new element allows the position
          // of the shape to be specified:          
          ElementGroup group = new ElementGroup(element);
          diagram.ElementOperations.MergeElementGroupPrototype(
            diagram, group.CreatePrototype(), PointD.ToPointF(diagramDragEventArgs.MousePosition));
        }
        t.Commit();
      }
    }
  }
}

Ff972471.collapse_all(zh-tw,VS.110).gif驗證條件約束

驗證方法標設出來ValidationExtension屬性,由 DSL,而也會產生ValidationMethodAttribute。此方法可以出現在任何未標記的屬性程式碼的類別。

如需詳細資訊,請參閱 網域指定的語言中的驗證

using Company.MyDsl;
using Company.MyDsl.ExtensionEnablement;
using Microsoft.VisualStudio.Modeling.Validation;

namespace MefExtension
{
  class MyValidationExtension // Can be any class.
  {
    // SAMPLE VALIDATION METHOD.
    // All validation methods have the following attributes.

    // Specific to the extended DSL:
    [MyDslValidationExtension] 

    // Determines when validation is applied:
    [ValidationMethod(
       ValidationCategories.Save
     | ValidationCategories.Open
     | ValidationCategories.Menu)]
    
    /// <summary>
    /// When validation is executed, this method is invoked
    /// for every element in the model that is an instance
    /// of the second parameter type.
    /// </summary>
    /// <param name="context">For reporting errors</param>
    /// <param name="elementToValidate"></param>
    private void ValidateClassNames
      (ValidationContext context,
       // Type determines to what elements this will be applied:
       ExampleElement elementToValidate)
    { 
      // Write code here to test values and links.
      if (elementToValidate.Name.IndexOf(' ') >= 0)
      {
        // Log any unacceptable values:
        context.LogError(
          // Description:
          "Name must not contain spaces" 
          // Error code unique to this type of error:
          , "MyDsl001" 
          // Element to highlight when user double-clicks error:
          , elementToValidate); 
} } } }

請參閱

概念

Managed Extensibility Framework (MEF)

HOW TO:加入拖放處理常式

網域指定的語言中的驗證

其他資源

VSIX 部署