次の方法で共有


MEF による DSL の拡張

Managed Extensibility Framework を使用 (DSL) して exntend ドメイン固有言語できます (MEF)。 自分または他の開発者はDSL の定義とプログラム コードを変更せずに DSL の拡張機能を作成します。 このような拡張はメニュー コマンドドラッグ アンド ドロップ ハンドラーおよび妥当性確認です。 ユーザーはDSL をインストールせずにオプションで拡張機能をインストールします。

またDSL の MEF を有効にするとすべて DSL とともにビルド DSL の機能の一部を書き込むことは簡単になります。

MEF の詳細については、「Managed Extensibility Framework (MEF)」を参照してください。

MEF が拡張ユースを有効にするには

  1. DslPackage のプロジェクト内の MefExtension という名前の新しいフォルダーを作成します。 これに次のファイルを追加します :

    ファイル名

    ファイルの内容

    CommandExtensionVSCT.tt

    重要

    DslPackage GeneratedCode \ \ Constants.tt で定義される GUID CommandSetId と同じである場合はこのファイルの 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 *** スイッチの少なくとも 1 つがを使用して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" #>
    1. Dsl のプロジェクト内の MefExtension という名前の新しいフォルダーを作成します。 これに次のファイルを追加します :

      ファイル名

      Content

      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" #>
    2. DslPackage\Commands.vsct という名前の既存ファイルに次の行を追加します :

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

      <Include> の既存のディレクティブの後に行を挿入します。

    3. 開いている DslDefinition.dsl。

    4. DSL のエクスプローラーで[入力] ENT0ENT を選択します。

    5. [プロパティ] ウィンドウで***** Uses... ***** という名前のプロパティのうち少なくとも 1 つが true であることを確認します。

    6. ソリューション エクスプローラーのツール バーでENT0ENT [] をクリックします。

      従属ファイルはファイルの下に追加したに表示されます。

    7. ソリューションをビルドする場合でも動作することを確認するために実装します。

    DSL はMEF 有効になります。 メニュー コマンドを作成できますがMEF の拡張としてハンドラーと検証制約を身振りに示します。 そのほかのカスタム コードとともに DSL のソリューションでこれらの拡張機能を作成できます。 また自分または他の開発者はDSL を拡張 Visual Studio の別の拡張機能を作成できます。

    MEF 有効なユース ケースの拡張機能の作成

    独りで作成される MEF 有効な DSL または他のユーザーにアクセスできる場合そのための拡張機能を作成できます。 拡張子がメニュー コマンドを追加するために使用できますがハンドラーまたは検証制約を身振りに示します。 これらの拡張機能を作成するにはVisual Studio Extension (VSIX) のソリューションを使用します。 ソリューションに 2 部分があります : コード アセンブリを作成するクラス ライブラリ プロジェクトおよびプロジェクトはVSIX パッケージ アセンブリ。

    DSL の拡張機能の VSIX を作成するには

    1. 新しいクラス ライブラリ プロジェクトを作成します。 これはENT0ENT [出力] ダイアログ ボックスでまたは *** Visual C# *** [入力] ENT1ENT を選択するかENT4ENT [] を選択します。

    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 プロジェクトを作成します。 これはENT0ENT [出力] ダイアログ ボックスでまたは ***** Visual C# *****ENT1ENT を展開し[ENT4ENT] をクリックし次に [入力] ENT6ENT を選択します。

    5. ソリューション エクスプローラーでVSIX プロジェクトを右クリックしを ENT0ENT [] をクリックします。

    6. 新しいプロジェクトにsource.extension.vsixmanifest を開きます。

    7. [コンテンツの追加] をクリックします。 ダイアログ ボックスで***** MEF Component ***** に コンテンツ タイプ クラス ライブラリ プロジェクトに ソース プロジェクト を設定します。

    8. DSL の VSIX への参照を追加します。

      1. source.extension.vsixmanifest ではENT0ENT [] をクリックします。

      2. ダイアログ ボックスでDSL の VSIX ファイルを ENT0ENT [] をクリックしを見つけます。 VSIX ファイルは DslPackage\bin\* の DSL のソリューションをビルドします。

        これはユーザーが DSL および拡張子を同時にインストールすることができます。 ユーザーが既に DSL をインストールし拡張子だけがインストールされます。

    9. source.extension.vsixmanifest の他のフィールドを確認および更新します。 [入力] ENT0ENT をクリックし正しい Visual Studio のエディションが設定されていることを確認します。

    10. クラス ライブラリ プロジェクトにコードを追加します。 ガイドとして次のセクションの例を使用します。

      コマンドジェスチャおよび検証クラスをいくつでも追加できます。

    11. 拡張機能をテストするにはF5 を押します。 Visual Studio の実験用インスタンスでDSL のサンプル ファイルを作成するか開きます。

    DSL の書き込み MEF の拡張子

    別の DSL の拡張機能ソリューションのアセンブリ コード プロジェクトの拡張機能を作成できます。 コマンドジェスチャ書き込みと DSL の一部として検証コードに簡単にする DslPackage プロジェクトを MEF を使用できます。

    メニュー コマンド

    メニュー コマンドを作成するには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"; }
        }
      }
    }
    

    ジェスチャハンドラー

    ジェスチャ ハンドラーはいずれも内部または外部の Visual Studio から図にドラッグするオブジェクトを処理できます。 次の例ではユーザーが図にエクスプローラーからファイルをドラッグすることができます。 またファイル名を持つ要素を作成します。

    他の DSL モデルおよび UML モデルからのドラッグを処理するためのハンドラーを記述できます。 詳細については、「方法: ドラッグ アンド ドロップ ハンドラーを追加する」を参照してください。

    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();
          }
        }
      }
    }
    

    検証制約

    検証メソッドはDSL によって生成されるとValidationMethodAttribute で示されます ValidationExtension の属性。 メソッドは属性でそのすべてのクラスで使用できます。

    詳細については、「ドメイン固有言語における検証」を参照してください。

    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)

    方法: ドラッグ アンド ドロップ ハンドラーを追加する

    ドメイン固有言語における検証

    その他の技術情報

    VSIX 配置