Share via


Cómo: Ampliar el diseñador de lenguajes específicos de dominio

Puede crear extensiones al diseñador que utiliza para editar las definiciones ADSL.Tipos de extensión que puede hacer incluyen que agrega comandos de menú, agregar controladores para los gestos de arrastre y haga doble clic en, y reglas que se desencadenan cuando los tipos determinados de valores o de cambio de las relaciones.Las extensiones se pueden empaquetar como extensión de integración de Visual Studio (VSIX) y distribuir a otros usuarios.

Para el código de ejemplo y obtener más información acerca de esta característica, vea Visual Visualización y modelado del sitio web de SDK (VMSDK)Studio.

Determinación de la solución

Configurar un proyecto que contiene el código de la extensión, y un proyecto VSIX que exporta el proyecto.Una solución puede contener otros proyectos que se escriban en el mismo VSIX.

Para crear un DSL Diseñador Extension Solution

  1. Cree un nuevo proyecto mediante la plantilla de proyecto biblioteca de clases.En el cuadro de diálogo de Nuevo proyecto , haga clic Visual C# y después haga clic en el medio Biblioteca de clasesde la ventana.

    Este proyecto contendrá código de extensiones.

  2. Cree un nuevo proyecto mediante la plantilla de proyecto VSIX.En el cuadro de diálogo de Nuevo proyecto , expanda Visual C#, haga clic Extensibilidady, en Proyecto VSIXseleccione ventana central.

    Seleccione Agregar a solución.

    Source.extension.vsixmanifest se abre en el editor de manifiestos VSIX.

  3. Sobre el campo de contenido, haga clic en Agregar contenido.

  4. En el cuadro de diálogo de Agregar contenido , establezca Seleccione un tipo de contenido a Componente MEF, y el conjunto Proyecto al proyecto de biblioteca de clases.

  5. Haga clic en Ediciones seleccionar y asegúrese de que Visual Studio Ultimate está activado.

  6. Asegúrese de que el proyecto VSIX es el proyecto de inicio de la solución.

  7. En el proyecto de biblioteca de clases, agregue referencias a los ensamblados siguientes:

    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

Pruebas e implementación

Para probar extensiones cualquiera de los en este tema, compile y ejecute la solución.Se abre una instancia experimental de Visual Studio.En esta instancia, abra una solución ADSL.Edite el diagrama de DslDefinition.El comportamiento de la extensión puede considerarse.

Para implementar extensiones a Visual Studioprincipal, y otros equipos, siga estos pasos:

  1. Busque el archivo de instalación VSIX, en el proyecto VSIX en bin \ * \ *.vsix

  2. Copie este archivo en el equipo de destino y, en el Explorador de Windows (o el Explorador de archivos), haga doble clic en.

    El administrador de extensiones de Visual Studio abre para confirmar que la extensión ha instalado.

Para desinstalar la extensión, siga estos pasos:

  1. en Visual Studio, en el menú de Herramientas , haga clic Administrador de extensiones.

  2. Seleccione la extensión y la elimina.

Agregar un comando de menú contextual

Para que un comando de menú contextual aparece en la superficie del diseñador ADSL o en la ventana Explorador de DSL, escriba una clase que es similar al siguiente.

La clase debe implementar ICommandExtension y debe tener el atributo 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"; }
    }
  }
}

Administrar gestos del mouse

El código es similar al código del comando de menú.

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

Responder a los cambios de valor

Este controlador necesita un modelo de dominio funcionar correctamente.Se proporciona un modelo de dominio simple.

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

El código siguiente implementa un modelo simple.Cree un nuevo GUID para reemplazar el marcador.

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

    }
}