Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Anda dapat memperluas bahasa khusus domain (DSL) Anda dengan menggunakan Managed Extensibility Framework (MEF). Anda atau pengembang lain akan dapat menulis ekstensi untuk DSL tanpa mengubah definisi DSL dan kode program. Ekstensi tersebut mencakup perintah menu, penangan seret dan letakkan, dan validasi. Pengguna akan dapat memasang DSL Anda, lalu secara opsional memasang ekstensi untuk DSL.
Selain itu, ketika Anda mengaktifkan MEF di DSL Anda, Anda dapat lebih mudah untuk menulis beberapa fitur DSL Anda, bahkan jika semuanya dibangun bersama dengan DSL.
Untuk mendapatkan informasi selengkapnya tentang MEF, lihat Managed Extensibility Framework (MEF).
Untuk mengaktifkan DSL Anda akan diperluas oleh MEF
Buat folder baru bernama MefExtension di dalam proyek DslPackage. Tambahkan file berikut ke dalamnya:
Nama file:
CommandExtensionVSCT.ttPenting
Atur GUID dalam file ini agar sama dengan GUID CommandSetId yang ditentukan dalam DslPackage\GeneratedCode\Constants.tt
<#@ 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" #>Nama file:
CommandExtensionRegistrar.tt<#@ Dsl processor="DslDirectiveProcessor" requires="fileName='..\..\Dsl\DslDefinition.dsl'" #> <#@ include file="DslPackage\CommandExtensionRegistrar.tt" #>Nama file:
ValidationExtensionEnablement.tt<#@ Dsl processor="DslDirectiveProcessor" requires="fileName='..\..\Dsl\DslDefinition.dsl'" #> <#@ include file="DslPackage\ValidationExtensionEnablement.tt" #>Nama file:
ValidationExtensionRegistrar.ttJika Anda menambahkan file ini, Anda harus mengaktifkan validasi di DSL Anda dengan menggunakan minimal salah satu sakelar dalam EditorValidation di DSL Explorer.
<#@ Dsl processor="DslDirectiveProcessor" requires="fileName='..\..\Dsl\DslDefinition.dsl'" #> <#@ include file="DslPackage\ValidationExtensionRegistrar.tt" #>Nama file:
PackageExtensionEnablement.tt<#@ Dsl processor="DslDirectiveProcessor" requires="fileName='..\..\Dsl\DslDefinition.dsl'" #> <#@ include file="DslPackage\PackageExtensionEnablement.tt" #>Buat folder baru bernama MefExtension di dalam proyek Dsl. Tambahkan file berikut ke dalamnya:
Nama file:
DesignerExtensionMetaDataAttribute.tt<#@ Dsl processor="DslDirectiveProcessor" requires="fileName='..\..\Dsl\DslDefinition.dsl'" #> <#@ include file="Dsl\DesignerExtensionMetadataAttribute.tt" #>Nama file:
GestureExtensionEnablement.tt<#@ Dsl processor="DslDirectiveProcessor" requires="fileName='..\..\Dsl\DslDefinition.dsl'" #> <#@ include file="Dsl\GestureExtensionEnablement.tt" #>Nama file:
GestureExtensionController.tt<#@ Dsl processor="DslDirectiveProcessor" requires="fileName='..\..\Dsl\DslDefinition.dsl'" #> <#@ include file="Dsl\GestureExtensionController.tt" #>Tambahkan baris berikut ke file yang sudah ada yang bernama DslPackage\Commands.vsct:
<Include href="MefExtension\CommandExtensionVSCT.vsct"/>Sisipkan baris setelah arah
<Include>yang ada.Buka DslDefinition.dsl.
Di DSL Explorer, buka Editor\Validation.
Di jendela Properti, pastikan bahwa minimal salah satu properti bernama Uses adalah
true.Klik Ubah Semua Template di toolbar Penjelajah Solusi.
File anak perusahaan muncul di bawah setiap file yang Anda tambahkan.
Bangun dan jalankan solusi untuk memverifikasi bahwa solusi masih berfungsi.
DSL Anda sekarang diaktifkan MEF. Anda dapat menulis perintah menu, penangan gerakan, dan batasan validasi sebagai ekstensi MEF. Anda dapat menulis ekstensi ini dalam solusi DSL Anda bersama dengan kode kustom lainnya. Selain itu, Anda atau pengembang lain dapat menulis ekstensi Visual Studio terpisah yang memperluas DSL Anda.
Membuat ekstensi untuk DSL berkemampuan MEF
Jika Anda memiliki akses ke DSL berkemampuan MEF yang dibuat sendiri atau orang lain, Anda dapat menulis ekstensi untuk itu. Ekstensi dapat digunakan untuk menambahkan perintah menu, penangan gerakan, atau batasan validasi. Untuk menulis ekstensi ini, Anda menggunakan solusi ekstensi Visual Studio (VSIX). Solusinya memiliki dua bagian: proyek pustaka kelas .NET Framework yang membangun rakitan kode, dan proyek VSIX yang mengemas rakitan.
Untuk membuat ekstensi DSL VSIX
Buat proyek Pustaka Kelas .NET Framework.
Dalam proyek baru, tambahkan referensi ke rakitan DSL.
Rakitan ini biasanya memiliki nama yang berakhiran dengan “.Dsl.dll”.
Jika Anda memiliki akses ke proyek DSL, Anda dapat menemukan file rakitan di bawah direktori Dsl\bin\*
Jika Anda memiliki akses ke file DSL VSIX, Anda dapat menemukan rakitan dengan mengubah ekstensi nama file dari file VSIX menjadi “.zip”. Dekompresi file .zip.
Tambahkan referensi ke rakitan .NET berikut:
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
Buat proyek dari proyek VSIX baru.
Di Penjelajah Solusi, klik kanan proyek VSIX dan pilih Atur sebagai Proyek Startup.
Dalam proyek baru, buka source.extension.vsixmanifest.
Klik Tambahkan Konten. Dalam kotak dialog, atur Jenis Konten ke Komponen MEF, dan Proyek Sumber ke proyek pustaka kelas Anda.
Tambahkan referensi VSIX ke DSL.
Di source.extension.vsixmanifest, klik Tambahkan Referensi
Dalam kotak dialog, klik Tambahkan Payload lalu temukan file VSIX DSL. File VSIX dibangun dalam solusi DSL, di DslPackage\bin\*.
Hal ini memungkinkan pengguna memasang DSL dan ekstensi Anda secara bersamaan. Jika pengguna telah memasang DSL, hanya ekstensi Anda yang akan dipasang.
Tinjau dan perbarui kolom lain dari source.extension.vsixmanifest. Klik Pilih Edisi dan verifikasi bahwa edisi Visual Studio yang benar telah diatur.
Tambahkan kode ke proyek pustaka kelas .NET Framework. Gunakan contoh di bagian berikutnya sebagai panduan.
Anda dapat menambahkan sejumlah kelas perintah, gerakan, dan validasi.
Untuk menguji ekstensi, tekan F5. Dalam instans eksperimental Visual Studio, buat atau buka file contoh DSL.
Menulis ekstensi MEF untuk DSL
Anda dapat menulis ekstensi dalam proyek kode rakitan dari solusi ekstensi bahasa khusus domain terpisah. Anda juga dapat menggunakan MEF dalam proyek DslPackage Anda, sebagai cara mudah untuk menulis perintah, gerakan, dan kode validasi sebagai bagian dari bahasa khusus domain.
Perintah Menu
Untuk menulis perintah menu, tentukan kelas yang menerapkan ICommandExtension dan mengawali kelas dengan atribut yang ditentukan dalam DSL Anda, bernama YourDslCommandExtension. Anda dapat menulis lebih dari satu kelas perintah menu.
QueryStatus() dipanggil setiap kali pengguna mengeklik kanan diagram. Ini harus memeriksa pilihan saat ini dan mengatur command.Enabled untuk menunjukkan waktu perintah berlaku.
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"; }
}
}
}
Penangan Gerakan
Penangan gerakan dapat menangani objek yang diseret ke diagram dari mana saja, di dalam atau di luar Visual Studio. Contoh berikut memungkinkan pengguna menyeret file dari Windows Explorer ke diagram. Hal ini membuat elemen yang memuat nama file.
Anda dapat menulis penangan untuk menangani seret dari model bahasa khusus domain lain dan model UML. Untuk mendapatkan informasi selengkapnya, lihat Cara: Menambahkan Penangan Seret dan Letakkan.
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();
}
}
}
}
Batasan validasi
Metode validasi ditandai oleh atribut ValidationExtension yang dihasilkan oleh bahasa khusus domain, dan juga oleh ValidationMethodAttribute. Metode dapat muncul di kelas apa pun yang tidak ditandai oleh atribut.
Untuk informasi selengkapnya, lihat Validasi dalam Bahasa Khusus Domain.
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);
} } } }