Condividi tramite


Procedura: estendere la finestra di progettazione di linguaggio specifico di dominio

È possibile creare estensioni alla finestra di progettazione utilizzata per modificare le definizioni DSL.Tipi di estensioni che è possibile includere i controlli menu di aggiunta, aggiunta di gestori per trascinamento e fare doppio clic sui movimenti e regole che vengono attivate quando determinati tipi di valori o di modifiche di relazioni.Le estensioni possono essere compresse come Visual Studio integration extension (VSIX) e distribuire ad altri utenti.

Per il codice di esempio e ulteriori informazioni su questa funzionalità, vedere Visual Studio Sito Web dell'sdk di visualizzazione e modellazione (VMSDK).

Installazione della soluzione

Un progetto che contiene il codice dell'estensione e un progetto VSIX che esporta il progetto.La soluzione può contenere altri progetti coinvolti nello stesso progetto VSIX.

Per creare una soluzione di estensione di progettazione DSL

  1. Creare un nuovo progetto utilizzando il modello di progetto Libreria di classi.Nella finestra di dialogo Nuovo progetto fare clic su, Visual C# quindi scegliere Classemedio della finestra.

    Questo progetto contiene codice delle estensioni.

  2. Creare un nuovo progetto utilizzando il modello di progetto VSIX.Nella finestra di dialogo Nuovo progetto, espandere Visual C#, scegliere Extensibilityquindi nella finestra centrale Progetto VSIXselezionato.

    Selezionare Aggiungi a soluzione.

    Source.extension.vsixmanifest verrà aperto nell'editor del manifesto VSIX.

  3. Nel campo di contenuto, fare clic Aggiungi contenuto.

  4. Nella finestra di dialogo Aggiungi contenuto, impostare Selezionare un tipo di contenuto a Componente MEFe il set Progetto al progetto Libreria di classi.

  5. Fare clic Selezionare i problemi e verificare che Visual Studio ultimate sia selezionato.

  6. Verificare che il progetto VSIX sia il progetto di avvio della soluzione.

  7. Nel progetto Libreria di classi, aggiungere riferimenti agli assembly seguenti:

    Microsoft.VisualStudio.CoreUtility

    Microsoft.VisualStudio.Modeling.Sdk.11.0

    Microsoft.VisualStudio.Modeling.Sdk.Diagrams.11.0

    Microsoft.VisualStudio.Modeling.Sdk.DslDefinition.11.0

    Microsoft.VisualStudio.Modeling.Sdk.Integration.11.0

    System.ComponentModel.Composition

    System.Drawing

    System.Drawing.Design

    System.Windows.Forms

Test e distribuzione

Per testare una qualsiasi delle estensioni in questo argomento, compilare ed eseguire la soluzione.Verrà aperta un'istanza sperimentale di Visual Studio.In questo caso, aprire una soluzione DSL.Modificare il diagramma di DslDefinition.Il comportamento di estensione può essere visualizzato.

Per distribuire le estensioni a Visual Studioprincipale e su altri computer, seguenti operazioni:

  1. Individuare il file di installazione VSIX, nel progetto VSIX in \ bin in * \ *.vsix

  2. Copiare il file nel computer di destinazione e quindi in Esplora risorse (o Esplora file), vi fa doppio clic su.

    Visual Studio Gestione estensioni verrà aperto per confermare che l'estensione è stata installata.

Per disinstallare l'estensione, seguire questi passaggi:

  1. in Visual Studio, scegliere dal menu Strumenti, scegliere Gestione estensioni.

  2. Selezionare l'estensione ed eliminarla.

Aggiunta di comando del menu di scelta rapida

Per eseguire un comando del menu di scelta rapida a essere visualizzato nella finestra di progettazione DSL o nella finestra di esplorazione DSL, scrivere una classe che è simile al seguente.

La classe deve implementare ICommandExtension e deve includere l'attributo DslDefinitionModelCommandExtension.

using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using Microsoft.VisualStudio.Modeling.Diagrams;
using Microsoft.VisualStudio.Modeling.Diagrams.ExtensionEnablement;
using Microsoft.VisualStudio.Modeling.DslDefinition;
using Microsoft.VisualStudio.Modeling.DslDefinition.ExtensionEnablement;
using Microsoft.VisualStudio.Modeling.DslDesigner;
using Microsoft.VisualStudio.Modeling.ExtensionEnablement;

namespace Fabrikam.SimpleDslDesignerExtension
{
  /// <summary>
  /// Command extending the DslDesigner.
  /// </summary>
  [DslDefinitionModelCommandExtension] 
  public class MyDslDesignerCommand : ICommandExtension
  {
    /// <summary>
    /// Selection Context for this command
    /// </summary>
    [Import]
    IVsSelectionContext SelectionContext { get; set; }

    /// <summary>
    /// Is the command visible and active?
    /// This is called when the user right-clicks.
    /// </summary>
    public void QueryStatus(IMenuCommand command)
    {
      command.Visible = true;
      // Is there any selected DomainClasses in the Dsl explorer?
      command.Enabled = 
        SelectionContext.AtLeastOneSelected<DomainClass>();

      // Is there any selected ClassShape on the design surface?
      command.Enabled |= 
        (SelectionContext.GetCurrentSelection<ClassShape>()
                .Count() > 0);
    }
    /// <summary>
    /// Executes the command 
    /// </summary>
    /// <param name="command">Command initiating this action</param>
    public void Execute(IMenuCommand command)
    {
      ...
    }
    /// <summary>
    /// Label for the command
    /// </summary>
    public string Text
    {
      get { return "My Command"; }
    }
  }
}

Spostamenti del mouse di gestione

Il codice è simile al codice del comando di menu.

[DslDefinitionModelGestureExtension]
 class MouseGesturesExtensions : IGestureExtension
 {
  /// <summary>
  /// Double-clicking on a shape representing a Domain model element displays this model element in a dialog box
  /// </summary>
  /// <param name="targetElement">Shape element on which the user has clicked</param>
  /// <param name="diagramPointEventArgs">event args for this double-click</param>
  public void OnDoubleClick(ShapeElement targetElement,
       DiagramPointEventArgs diagramPointEventArgs)
  {
   ModelElement modelElement = PresentationElementHelper.
        GetDslDefinitionModelElement(targetElement);
   if (modelElement != null)
   {
    MessageBox.Show(string.Format(
      "Double clicked on {0}", modelElement.ToString()), 
      "Model element double-clicked");
   }
  }


  /// <summary>
  /// Tells if the DslDesigner can consume the to-be-dropped information
  /// </summary>
  /// <param name="targetMergeElement">Shape on which we try to drop</param>
  /// <param name="diagramDragEventArgs">Drop event</param>
  /// <returns><c>true</c> if we can consume the to be dropped data, and <c>false</c> otherwise</returns>
  public bool CanDragDrop(ShapeElement targetMergeElement,
        DiagramDragEventArgs diagramDragEventArgs)
  {
   if (diagramDragEventArgs.Data.GetDataPresent(DataFormats.FileDrop))
   {
    diagramDragEventArgs.Effect = DragDropEffects.Copy;
    return true;
   }
   return false;
  }


  /// <summary>
  /// Processes the drop by displaying the dropped text
  /// </summary>
  /// <param name="targetMergeElement">Shape on which we dropped</param>
  /// <param name="diagramDragEventArgs">Drop event</param>
  public void OnDragDrop(ShapeElement targetDropElement, DiagramDragEventArgs diagramDragEventArgs)
  {
   if (diagramDragEventArgs.Data.GetDataPresent(DataFormats.FileDrop))
   {
    string[] droppedFiles = 
      diagramDragEventArgs.Data.
               GetData(DataFormats.FileDrop) as string[];
    MessageBox.Show(string.Format("Dropped text {0}",
        string.Join("\r\n", droppedFiles)), "Dropped Text");
   }
  }
 }

Risposta alle modifiche di valore

Questo gestore è necessario un modello di dominio per funzionare correttamente.Viene fornito un modello di dominio semplice.

using System.Diagnostics;
using Microsoft.VisualStudio.Modeling;
using Microsoft.VisualStudio.Modeling.DslDefinition;
namespace Fabrikam.SimpleDslDesignerExtension
{
  /// <summary>
  /// Rule firing when the type of a domain model property is changed. The change is displayed
  /// in the debugger (Output window of the Visual Studio instance debugging this extension)
  /// </summary>
  [RuleOn(typeof(PropertyHasType))]
  public class DomainPropertyTypeChangedRule : RolePlayerChangeRule
  {
    /// <summary>
    /// Method called when the Type of a Domain Property 
    /// is changed by the user in a DslDefinition
    /// </summary>
    /// <param name="e"></param>
    public override void RolePlayerChanged(RolePlayerChangedEventArgs e)
    {
      // We are only interested in the type
      if (e.DomainRole.Id == PropertyHasType.TypeDomainRoleId)
      {
        PropertyHasType relationship = 
           e.ElementLink as PropertyHasType;
        DomainType newType = e.NewRolePlayer as DomainType;
        DomainType oldType = e.OldRolePlayer as DomainType;
        DomainProperty property = relationship.Property;

         // We write about the Type change in the debugguer
        Debug.WriteLine(string.Format("The type of the Domain property '{0}' of domain class '{1}' changed from '{2}' to '{3}'",
          property.Name,
          property.Class.Name,
          oldType.GetFullName(false),
          newType.GetFullName(false))
} }  }  );

Il codice seguente viene implementato un semplice modello.Creare un nuovo GUID per sostituire il segnaposto.

using System;
using System.ComponentModel.Composition;
using Microsoft.VisualStudio.Modeling;
using Microsoft.VisualStudio.Modeling.DslDefinition;
namespace Fabrikam.SimpleDslDesignerExtension
{
    /// <summary>
    /// Simplest possible domain model 
    /// needed only for extension rules. 
    /// </summary>
    [DomainObjectId(SimpleDomainModelExtension.DomainModelId)]
    public class SimpleDomainModelExtension : DomainModel
    {
        // Id of this domain model extension 
        // Please replace this with a new GUID:
        public const string DomainModelId = 
                  "00000000-0000-0000-0000-000000000000";

        /// <summary>
        /// Constructor for the domain model extension
        /// </summary>
        /// <param name="store">Store in which the domain model will be loaded</param>
        public SimpleDomainModelExtension(Store store)
            : base(store, new Guid(SimpleDomainModelExtension.DomainModelId))
        {

        }

        /// <summary>
        /// Rules brought by this domain model extension
        /// </summary>
        /// <returns></returns>
        protected override System.Type[] GetCustomDomainModelTypes()
        {
            return new Type[] {
                     typeof(DomainPropertyTypeChangedRule)
                              };
        }
    }


    /// <summary>
    /// Provider for the DomainModelExtension
    /// </summary>
    [Export(typeof(DomainModelExtensionProvider))]    [ProvidesExtensionToDomainModel(typeof(DslDefinitionModelDomainModel))]
    public class SimpleDomainModelExtensionProvider 
          : DomainModelExtensionProvider
    {
        /// <summary>
        /// Extension model type
        /// </summary>
        public override Type DomainModelType
        {
            get
            {
                return typeof(SimpleDomainModelExtension);
            }
        }

    }
}