Jak: rozszerzenie Projektant języka specyficzne dla domeny
Można tworzyć rozszerzenia projektanta, używany do edycji definicji DSL.Typy rozszerzenia, które można wprowadzać obejmują dodawanie poleceń menu, dodawanie obsługi przeciągnij i kliknij dwukrotnie gesty i reguły, które są zmiany poszczególnych typów wartości lub relacji.Rozszerzenia można pakowane jako Visual Studio Integration Extension (VSIX) i rozprowadzane do innych użytkowników.
Przykładowy kod i uzyskać więcej informacji o tej funkcji, zobacz Visual Studio wizualizacji i witryny sieci Web modelowania SDK (VMSDK).
Konfigurowanie roztworu
Ustawianie projekt, który zawiera kod rozszerzenie programu i projektu VSIX, że wywóz projektu.Rozwiązanie może zawierać inne projekty, które są włączone do samego VSIX.
Aby utworzyć rozwiązanie rozszerzenie Projektant DSL
Tworzenie nowego projektu za pomocą szablonu Projekt biblioteki klas.W Nowy projekt okno dialogowe, kliknij przycisk Visual C# a następnie w środkowym oknie kliknij Biblioteka klas.
Ten projekt będzie zawierać kod użytkownika rozszerzeń.
Tworzenie nowego projektu za pomocą szablonu Projekt VSIX.W Nowy projekt okno dialogowe rozwiń Visual C#, kliknij rozszerzalności, a następnie w środkowym oknie Wybierz Projektu VSIX.
Wybierz dodać do roztworu.
Source.Extension.vsixmanifest zostanie otwarty w edytorze manifestu VSIX.
Powyżej zawartości pola, kliknij Dodaj zawartość.
W Dodaj zawartość okno dialogowe, set Wybierz typ zawartości do MEF składnikai projektu do projektu biblioteki klas.
Kliknij Zaznacz wersje i upewnij się, że Visual Studio Ultimate jest sprawdzana.
Upewnij się, że projekt VSIX jest projektem uruchamiania roztworu.
W projekcie biblioteki klas Dodaj odwołania do następujących zespołów:
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
Testowanie i wdrażanie
Aby przetestować żadnego rozszerzenia, w tym temacie, tworzenie i uruchamianie roztworu.Wystąpienie doświadczalnych Visual Studio otwiera.Otwórz to wystąpienie roztwór DSL.Edytuj schemat DslDefinition.Zachowanie rozszerzenia są widoczne.
Wdrażanie rozszerzeń w głównym Visual Studiooraz z innymi komputerami, wykonaj następujące kroki:
Znajdź plik instalacyjny VSIX w projekcie VSIX bin\*\*.vsix
Skopiować ten plik na komputer docelowy, a następnie w Eksploratorze Windows (lub Eksploratora plików), kliknij go dwukrotnie.
Visual Studio Otwiera Extension Manager, aby potwierdzić, że zainstalowano rozszerzenia.
Aby odinstalować rozszerzenia, wykonaj następujące kroki:
w Visual Studio, z Narzędzia menu, kliknij Extension Manager.
Zaznacz rozszerzenie i usuń go.
Dodawanie polecenia Menu skrótów
Aby polecenie menu skrótów pojawiają się na powierzchni Projektant DSL lub w oknie Eksploratora DSL, należy napisać przypominającą następujące klasy.
Klasa musi implementować ICommandExtension i musi mieć atrybut 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"; }
}
}
}
Obsługa gesty myszy
Kod jest podobny do kodu polecenia 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");
}
}
}
Reagowanie na zmiany wartości
Ten program obsługi wymaga modelu domeny, aby działać poprawnie.Firma Microsoft udostępnia model domeny proste.
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))
} } } );
Poniższy kod implementuje prostego modelu.Utwórz nowy identyfikator GUID, aby zastąpić symbol zastępczy.
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);
}
}
}
}