Sdílet prostřednictvím


Postupy: Rozšíření návrháře jazyka specifického pro doménu

Provedete-li rozšíření Návrhář, které umožňují upravit definice DSL.Typy rozšíření, které můžete provést zahrnují přidání příkazů nabídky, přidání obslužné rutiny pro přetažení a poklepejte na gesta a pravidel, které se spouštějí při změně určitých typů hodnot nebo vztahy.Rozšíření lze zabaleny jako Visual Studio integrace rozšíření (VSIX) a distribuovat ostatním uživatelům.

Ukázkový kód a další informace o této funkci naleznete v části Visual Studio vizualizaci a modelování SDK (VMSDK) webu.

Nastavení řešení

Nastavení projektu, který obsahuje kód vaší rozšíření a VSIX projektu, který se exportuje projektu.Řešení mohou obsahovat projekty, které jsou součástí stejné VSIX.

Vytvořit řešení rozšíření Návrhář DSL

  1. Vytvoření nového projektu pomocí šablony projektu knihovna tříd.V Nový projekt dialogové okno, klepněte na tlačítko Visual C# a potom v prostředním okně klepněte na tlačítko Knihovna tříd.

    Tento projekt bude obsahovat kód vaší rozšíření.

  2. Vytvoření nového projektu pomocí šablony projektu VSIX.V Nový projekt dialogovém okně pole, rozbalte položku Visual C#, klepněte na tlačítko rozšířenía potom v prostředním okně vyberte VSIX projektu.

    Vyberte do roztoku přidejte.

    Source.Extension.vsixmanifest se otevře v editoru VSIX manifestu.

  3. Nad pole obsahu, klepněte na tlačítko Přidání obsahu.

  4. V Přidání obsahu dialogové okno, sada Vyberte typ obsahu na MEF součásta projektu projektu knihovny tříd.

  5. Klepněte na tlačítko Vyberte vydání a ujistěte se, že Visual Studio Ultimate je kontrolována.

  6. Přesvědčte se, zda projekt VSIX spuštění projektu roztoku.

  7. V projektu knihovny třídy přidáte odkazy na následující sestavení:

    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

Testování a nasazení

Testovat všechny přípony v tomto tématu, sestavit a spustit řešení.Experimentální výskyt Visual Studio otevře.V tomto případě otevřete DSL řešení.DslDefinition diagram upravte.Rozšíření chování lze vidět.

Nasazení rozšíření hlavní Visual Studioa k jiným počítačům, postupujte takto:

  1. Najít instalační soubor VSIX v VSIX projektu bin\*\*.vsix

  2. Zkopírujte tento soubor do cílového počítače a v programu Průzkumník Windows (nebo File Explorer), poklepejte na něj.

    Visual Studio Se otevře potvrdit, že byla nainstalována rozšíření Extension Manager.

Rozšíření odinstalovat, postupujte takto:

  1. v Visual Studio, Nástroje nabídky, klepněte na tlačítko Extension Manager.

  2. Vyberte příponu a odstraňte ji.

Přidání příkazu místní nabídky

Chcete-li příkaz z místní nabídky se zobrazují na povrchu Návrhář DSL nebo v okně Průzkumníka DSL, psát připomínající následující třídy.

Třída musí implementovat ICommandExtension a musí mít atribut 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"; }
    }
  }
}

Zpracování gesta myši

Kód podobný kód příkazu nabídky.

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

Reagovat na změny hodnot

Toto zpracování, musí model domény správně pracovat.Poskytujeme modelu domény jednoduchý.

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

Následující kód implementuje jednoduchého modelu.Vytvořte nový identifikátor GUID nahraďte zástupný symbol.

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

    }
}