Erweitern von DSL mittels MEF
Sie können exntend die domänenspezifische Sprache (DSL), indem Sie Managed Extensibility Framework (MEF) verwenden.Sie oder andere Entwickler sind in der Lage, Erweiterungen für das DSL zu schreiben, ohne die DSL-Definition und den Programmcode zu ändern.Solche Erweiterungen sind Menübefehle, Drag & Drop-Handler and Validation.Benutzer sind in der Lage, das DSL zu installieren und dann wahlweise Erweiterungen für diese Installation.
Wenn Sie außerdem in MEF DSL aktivieren, kann es für Sie einfacher sein, einige der Funktionen des DSL zu schreiben, auch wenn alle diese zusammen mit dem DSL erstellt werden.
Weitere Informationen über MEF finden Sie unter Managed Extensibility Framework (MEF).
Um das von MEF erweitert werden können, DSL
Erstellen Sie einen neuen Ordner mit dem MefExtensionDslPackage innerhalb des Projekts wird.Fügen Sie die folgenden Dateien hinzu:
Dateiname
Dateiinhalt
CommandExtensionVSCT.tt
WichtigLegen Sie den GUID in dieser Datei fest, die dieselben wie die GUID CommandSetId sein, das in DslPackage GeneratedCode " \ \ Constants.tt definiert ist<#@ 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
Wenn Sie diese Datei hinzufügen, müssen Sie die Validierung im DSL aktivieren, indem Sie mindestens einen der Schalter in Editor\Validierung in DSL-Explorer verwenden.
<#@ 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" #>
Erstellen Sie einen neuen Ordner mit dem MefExtensionDsl innerhalb des Projekts wird.Fügen Sie die folgenden Dateien hinzu:
Dateiname
Inhalt
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" #>
Fügen Sie die folgende Zeile der vorhandenen Datei DslPackage\Commands.vscthinzu:
<Include href="MefExtension\CommandExtensionVSCT.vsct"/>
Fügen Sie die Zeile nach den vorhandenen <Include>-Direktive ein.
Öffnen Sie DslDefinition.dsl.
In DSL-Explorer ausgewähltes Editor\Validierung.
Stellen Sie im Eigenschaftenfenster sicher, dass mindestens eine der Eigenschaften, die Verwendet... benannt werden, trueist.
Klicken Sie auf der Symbolleiste des Projektmappen-Explorers klicken Sie auf Alle Vorlagen transformieren.
benutzerfreundliche von Dateien werden unter alle Dateien, die Sie hinzugefügt haben.
Erstellen Sie die Projektmappe, und führen Sie es aus, um sicherzustellen, dass sie immer noch funktioniert.
Das DSL wird jetzt MEF-aktiviert.Sie schreiben, Menübefehle können sich bewegen und Handler als Validierungseinschränkungen MEF-Erweiterungen den Stift.Sie können diese Erweiterungen in der DSL-Projektmappe zusammen mit anderen benutzerdefinierten Code schreiben.Darüber hinaus können Sie oder andere Entwickler eigene Erweiterungen Visual Studio schreiben, die das DSL erweitern.
Eine Erweiterung für ein MEF-aktiviertes erstellen DSL
Wenn Sie den Zugriff auf ein MEF-aktivierten DSL verfügen, die von sich selbst oder auf eine andere Person erstellt wurde, können Sie Erweiterungen für diese schreiben.Die Erweiterungen können verwendet werden, um Menübefehle hinzufügen, werden Handler verschoben oder Validierungseinschränkungen den Stift.Um diese Erweiterungen zu erstellen, verwenden Sie eine Projektmappe Visual Studio Erweiterung (VSIX).Die Lösung besteht aus zwei Teilen: Ein Klassenbibliotheksprojekt, das den Code baugruppe erstellt und ein VSIX-Projekt dass Pakete die Assembly.
So erstellen Sie eine DSL-Erweiterung VSIX
Erstellen Sie ein neues Klassenbibliotheksprojekt.Klicken Sie dazu im Neues Projekt Dialogfeld, in Visual Basic oder Visual C# auswählen, und wählen Sie dann Klassenbibliothek.
Im neuen Klassenbibliotheksprojekt fügen Sie einen Verweis auf die Assembly des DSL hinzu.
Diese Assembly enthält normalerweise einen diesen Namen mit „endet. Dsl.dll“.
Wenn Sie den Zugriff auf den DSL-Projekt haben, können Sie die Assemblydatei unter dem Verzeichnis durchsuchen Dsl\bin\*
Wenn Sie den Zugriff auf die Datei DSL VSIX haben, können Sie die Assembly suchen, indem Sie die Dateinamenerweiterung der VSIX-Datei auf „.zip“ ändern.Dekomprimieren Sie die ZIP-Datei.
Fügen Sie Verweise auf die folgenden .NET-Assemblys hinzu:.
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
Erstellen Sie ein VSIX-Projekt in derselben Projektmappe.Klicken Sie dazu im Dialogfeld Neues Projekt , Visual Basic oder Visual C#, klicken Sie auf Erweiterungen, und wählen Sie dann VSIX-Projektaus.
Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf das VSIX-Projekt, und klicken dann auf Als Startprojekt festlegen.
Öffnen Sie im neuen Projekt source.extension.vsixmanifest.
Klicken Sie auf Inhalt hinzufügen.Legen Sie im Dialogfeld Inhaltstyp zu MEF-Komponenteauf das Klassenbibliotheksprojekt und Quellprojekt fest.
Fügen Sie dem DSL VSIX-Verweis hinzufügen.
In source.extension.vsixmanifestklicken Sie auf Verweis hinzufügen
Suchen Sie im Dialogfeld auf Nutzlast hinzufügen und anschließend die VSIX-Datei des DSL.Die VSIX-Datei ist die DSL-Projektmappe, in **DslPackage\bin\***integriert.
Auf diese Weise können Benutzer das DSL und die Erweiterung zur selben Zeit installiert wird.Wenn der Benutzer bereits das DSL installiert hat, werden nur die Erweiterung installiert ist.
Wiederholen Sie und aktualisieren Sie die anderen Felder aus source.extension.vsixmanifest.Klicken Sie auf Editionen auswählen , und stellen Sie sicher, dass die richtigen Visual Studio Editionen festgelegt werden.
Fügen Sie dem Klassenbibliotheksprojekt Code hinzu.Verwenden Sie die Beispiele im nächsten Abschnitt als Leitfaden.
Sie können eine beliebige Anzahl von Befehl, Aktion und Klassen für Validierungen hinzufügen.
So testen Sie die Erweiterung, drücken Sie F5.Klicken Sie in der experimentellen Instanz von Visual Studio, Erstellen oder öffnen Sie eine Datei mit DSL des Codebeispiels.
Erweiterungen des Schreibens MEF für DSL
Sie können Erweiterungen im Projekt Assemblycode DSL-Erweiterungs einer anderen Projektmappe schreiben.Sie können MEF im DslPackage-Projekt als auch eine bequeme Möglichkeit, Befehle auf Gesten und Validierungscode als Teil des DSL schreiben.
Menübefehle
Um einen Menübefehl zu schreiben, definieren Sie eine Klasse, die ICommandExtension Präfix und die Klasse, wobei das Attribut implementiert das im DSL mit dem Namen definierte TheDslCommandExtension.Sie können mehrere Menübefehlsklasse schreiben.
QueryStatus() wird immer dann aufgerufen, wenn der Benutzer auf das Diagramm mit der rechten Maustaste klickt.Es sollte der aktuellen Auswahl und den Satz command.Enabled überprüfen, um anzugeben, wann der Befehl anwendbar ist.
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"; }
}
}
}
Gestenhandler
Ein Gestenhandler kann die Objekte verarbeiten, die von einer beliebigen Stelle auf das Diagramm, innerem oder äußerem Visual Studiogezogen werden.Im folgenden Beispiel kann der Benutzer Dateien aus Windows Explorer in das Diagramm ziehen.Es erstellt Elemente, die die Dateinamen enthalten.
Sie können Handler schreiben, die von anderen Ziehen DSL-Modellen und FROM UML-Modelle zu verarbeiten.Weitere Informationen finden Sie unter Gewusst wie: Hinzufügen eines Drag & Drop-Handlers.
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();
}
}
}
}
Validierungseinschränkungen
Validierungsmethoden werden vom ValidationExtension-Attribut, das vom DSL generiert wird, sowie über ValidationMethodAttributemarkiert.Die Methode kann in einer beliebigen Klasse werden, die nicht von einem Attribut gekennzeichnet ist.
Weitere Informationen finden Sie unter Validierung in einer domänenspezifischen Sprache.
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);
} } } }
Siehe auch
Konzepte
Managed Extensibility Framework (MEF)
Gewusst wie: Hinzufügen eines Drag & Drop-Handlers
Validierung in einer domänenspezifischen Sprache