Condividi tramite


Estendere il DSL mediante MEF

È possibile exntend il linguaggio (DSL) specifico di dominio utilizzando managed extensibility Framework (MEF).L'utente o altri sviluppatori di scrivere estensioni del linguaggio DSL senza modificare la definizione e il codice del programma DSL.Tali estensioni includono i comandi di menu, i gestori trascinamento della selezione e la convalida.Gli utenti potranno installare il modello DSL e quindi facoltativamente installare le estensioni di per.

Inoltre, quando si attiva il framework MEF nel modello DSL, può essere più semplice scrivere alcune funzionalità del linguaggio DSL, anche se tutti compilati insieme al modello DSL.

Per ulteriori informazioni su MEF, vedere Managed Extensibility Framework (MEF).

Per consentire al modello DSL per essere esteso da MEF

  1. creare una nuova cartella denominata MefExtension in DslPackage progetto.Aggiungere i file seguenti in:

    Nome file

    Contenuto del file

    CommandExtensionVSCT.tt

    Nota importanteImportante
    Impostare il GUID in questo file per essere identici al GUID CommandSetId definito in DslPackage \GeneratedCode\Constants .tt
    <#@ 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

    Se si aggiunge questo file, è necessario abilitare la convalida del modello DSL utilizzando almeno una delle opzioni in editor \Validation nel modello DSL Esplora Risorse.

    <#@ 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. creare una nuova cartella denominata MefExtension in Dsl progetto.Aggiungere i file seguenti in:

    Nome file

    Contenuto

    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. Aggiungere la riga seguente al file esistente denominato DslPackage\Commands.vsct:

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

    Inserire la riga dopo l'esistenza <Include> direttiva.

  4. aprire DslDefinition.dsl.

  5. Nel modello DSL Esplora Soluzioni, selezionare editor \Validation.

  6. Nella Finestra Proprietà, accertarsi che almeno una delle proprietà disponga denominato utilizza… viene true.

  7. Nella barra degli strumenti di Esplora soluzioni, fare clic su Trasformazione di tutti i modelli.

    I file sussidiari vengono visualizzati sotto di ogni file che sono state aggiunte.

  8. Compilare ed eseguire la soluzione per verificare che è in uso.

Il modello DSL ora MEF-è abilitato.È possibile scrivere comandi di menu, di gestori movimenti e i vincoli di convalida come estensioni MEF.È possibile scrivere queste estensioni nella soluzione DSL insieme ad altro codice personalizzato.Inoltre, l'utente o altri sviluppatori possibile scrivere distinto Visual Studio Estensioni che estendono il modello DSL.

Creare un'estensione per un modello DSL MEF-abilitato

Se si ha accesso a un modello DSL MEF-abilitato creato da solo o a un altro utente, è possibile scrivere le estensioni di per.Le estensioni possono essere utilizzate per aggiungere i comandi di menu, di gestori movimenti, o i vincoli di convalida.Per creare queste estensioni, si utilizza un oggetto Visual Studio Soluzione extension (VSIX).La soluzione è costituito da due parti: un progetto libreria di classi che compila l'assembly di codice e un progetto VSIX che consente di creare l'assembly.

Per creare un'estensione VSIX DSL

  1. Creare un nuovo progetto di libreria di classi.A tale scopo, in nuovo progetto finestra di dialogo, selezionare Visual Basic o Visual C# quindi selezionare libreria di classi.

  2. Nel nuovo progetto Libreria di classi, aggiungere un riferimento a un assembly del linguaggio DSL.

    • Questo assembly in genere ha un nome che termina con “. Dsl.dll„.

    • Se si dispone di accesso al progetto di modello DSL, è possibile trovare il file di assembly nella directory Dsl\bin\*

    • Se si dispone di accesso al file di IL progetto VSIX, è possibile trovare l'assembly modificando l'estensione del file VSIX “in .zip„.Decomprimere il file .zip.

  3. Aggiungere i riferimenti ai seguenti assembly .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. Creare un progetto VSIX nella stessa soluzione.A tale scopo, in nuovo progetto la finestra di dialogo espandere, Visual Basic o Visual C#, quindi Estensibilitàquindi selezionare Progetto VSIX.

  5. In Esplora soluzioni, fare clic con il pulsante destro del mouse sul progetto VSIX e scegliere set come progetto di avvio.

  6. Nel nuovo progetto, aprire source.extension.vsixmanifest.

  7. Fare clic su Aggiungi contenuto.Nella finestra di dialogo, impostare tipo di contenuto in Componente MEFe progetto originale il progetto Libreria di classi.

  8. Aggiungere un riferimento vsix nel modello DSL.

    1. in source.extension.vsixmanifest, quindi aggiungere il riferimento

    2. Nella finestra di dialogo, fare clic su aggiungere il payload quindi individuare il file VSIX del linguaggio DSL.Il file VSIX è incorporato la soluzione DSL, in DslPackage\bin\*.

      In questo modo è possibile installare il modello DSL e l'estensione contemporaneamente.Se l'utente ha già installato il modello DSL, solo l'estensione verrà installata.

  9. rivedere e aggiornare gli altri campi di source.extension.vsixmanifest.Fare clic su Problemi selezionate e verificare che il corretto Visual Studio i problemi devono essere impostate.

  10. Aggiungere codice al progetto Libreria di classi.Utilizzare gli esempi riportati nella sezione successiva come guida.

    È possibile aggiungere un numero illimitato di comando, di spostamento e di classi di convalida.

  11. Per testare l'estensione, stampa F5.Nell'istanza sperimentale di Visual Studio, creare o aprire un file di esempio DSL.

Estensioni MEF di scrittura per DSLs

È possibile scrivere estensioni nel progetto di codice assembly di una soluzione separata di estensione DSL.È inoltre possibile utilizzare il framework MEF nel progetto DslPackage, come comodo a scrivere i comandi, movimenti e il codice di convalida come parte del modello DSL.

Ff972471.collapse_all(it-it,VS.110).gifComandi di menu

Per scrivere un comando di menu, definire una classe che implementa ICommandExtension e alla classe con l'attributo definito nel modello DSL, denominato TheDslCommandExtension.È possibile scrivere più di uno classe del comando di menu.

QueryStatus() viene chiamato ogniqualvolta l'utente fa clic con il pulsante destro del mouse sul diagramma.Deve controllare la selezione e l'insieme corrente command.Enabled per indicare quando il comando è applicabile.

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(it-it,VS.110).gifgestori movimenti

Un gestore movimenti possibile gestire gli oggetti trascinati nel diagramma da qualsiasi punto, all'interno o a Visual Studio.L'esempio seguente consente di trascinare i file da esplora risorse nel diagramma.Crea gli elementi contenenti i nomi file.

È possibile scrivere gestori per la gestione di trascinamento da altri modelli DSL e modelli UML.Per ulteriori informazioni, vedere Procedura: aggiungere un gestore di trascinamento della selezione.

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(it-it,VS.110).gifvincoli di convalida

I metodi di convalida sono contrassegnati da ValidationExtension attributo generato dal modello DSL e anche da ValidationMethodAttribute.Il metodo può trovarsi in qualsiasi classe che non è identificato da un attributo.

Per ulteriori informazioni, vedere Convalida in un linguaggio specifico di dominio.

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

Vedere anche

Concetti

Managed Extensibility Framework (MEF)

Procedura: aggiungere un gestore di trascinamento della selezione

Convalida in un linguaggio specifico di dominio

Altre risorse

Distribuzione VSIX