MEF를 사용하여 DSL 확장
확장성 프레임 워크 (MEF) 관리를 사용 하 여 도메인 관련 언어를 (DSL) exntend 있습니다.사용자나 다른 개발자가 DSL 정의 하 고 프로그램 코드를 변경 하지 않고는 DSL에 대 한 확장을 작성할 수 있습니다.그러한 확장 메뉴 명령, 끌어서 놓기 처리기 및 유효성 검사를 포함합니다.사용자를 DSL을 설치 하 고 다음 필요에 따라 확장을 설치 수 있습니다.
MEF는 DSL을 사용 하는 경우 모두 DSL과 함께 작성 된 경우에 또한이 쉽게 기능을 DSL 작성할 수 수 있습니다.
MEF에 대 한 자세한 내용은 참조 하십시오. MEF(Managed Extensibility Framework).
MEF에서 확장 하 여 DSL을 사용 하려면
라는 새 폴더를 만듭니다 MefExtension 내부에서 DslPackage 프로젝트입니다.다음 파일을 추가 합니다.
파일 이름
파일 내용
CommandExtensionVSCT.tt
중요GUID에서이 파일을 Dslpackage\generatedcode\constants.tt에서 정의 된 GUID CommandSetId 수 설정<#@ 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
이 파일을 추가 하는 경우의 스위치 중 하나를 사용 하 여를 DSL에 유효성을 설정 해야 Editor\Validation DSL 탐색기에서.
<#@ 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" #>
라는 새 폴더를 만듭니다 MefExtension 내부에서 Dsl 프로젝트입니다.다음 파일을 추가 합니다.
파일 이름
Content
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" #>
지정 된 기존 파일에 다음 줄을 추가 합니다. DslPackage\Commands.vsct:
<Include href="MefExtension\CommandExtensionVSCT.vsct"/>
기존 후 줄 삽입 <Include> 지시문입니다.
Dsldefinition.dsl를 엽니다.
DSL 탐색기 선택 Editor\Validation.
속성 창에서 속성을 하나 이상 이라는 것이 있는지 확인 하십시오 사용 하 여... is true.
솔루션 탐색기 도구 모음에서 모든 템플릿 변환.
보조 파일은 각 추가 파일 아래 나타납니다.
빌드한 후 솔루션 여전히 작동 하는지 확인 합니다.
이제를 DSL MEF 사용이 가능 합니다.MEF 확장으로는 메뉴 명령, 제스처 처리기 및 유효성 검사 제약 조건을 작성할 수 있습니다.다른 사용자 지정 코드와 함께 DSL 솔루션에서 이러한 확장을 작성할 수 있습니다.또한 사용자나 다른 개발자가 별도 쓸 수 있습니다 Visual Studio 를 DSL을 확장 하는 확장입니다.
MEF 가능한 DSL에 대 한 확장 만들기
자신이 나 다른 사용자가 만든 MEF 가능한 DSL에 액세스할 수 있으면 확장을 작성할 수 있습니다.메뉴 명령, 제스처 처리기 또는 유효성 검사 제약 조건을 추가 하는 확장을 사용할 수 있습니다.이러한 확장을 작성 하려면 사용 하는 Visual Studio 확장명 (VSIX) 솔루션입니다.솔루션 두 부분으로 이루어져 있습니다: 코드 어셈블리를 작성 하는 클래스 라이브러리 프로젝트와 어셈블리 패키지 VSIX 프로젝트입니다.
DSL 확장 VSIX 생성 하기
새 클래스 라이브러리 프로젝트를 만듭니다.이렇게 하는 새 프로젝트 선택 대화 상자에서 Visual Basic 또는 C# 다음 선택 클래스 라이브러리.
새 클래스 라이브러리 프로젝트에는 DSL의 어셈블리에 참조를 추가 합니다.
이 어셈블리는 일반적으로 끝나는 이름이 있습니다 ".Dsl.dll "입니다.
DSL 프로젝트에 액세스할 수 있으면 디렉터리 아래에 있는 어셈블리 파일을 찾을 수 있습니다.Dsl\bin\*
DSL VSIX 파일에 액세스할 경우에 ".zip" VSIX 파일의 파일 이름 확장명을 변경 하 여 어셈블리를 찾을 수 있습니다..Zip 파일의 압축을 풀.
다음 .NET 어셈블리에 대한 참조를 추가합니다.
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
VSIX 프로젝트가 동일한 솔루션에 만듭니다.에 이렇게 하는 새 프로젝트 대화 상자에서 확장 Visual Basic 또는 C#, 클릭 확장성, 다음을 선택 하 고 VSIX 프로젝트.
솔루션 탐색기에서 VSIX 프로젝트를 마우스 오른쪽 단추로 클릭 하 고 다음을 클릭 시작 프로젝트로 설정.
새 프로젝트를 열고 source.extension.vsixmanifest.
콘텐츠 추가를 클릭합니다.대화 상자에서 설정 콘텐츠 형식 에 MEF 구성 요소, 및 소스 프로젝트 클래스 라이브러리 프로젝트입니다.
DSL VSIX 참조를 추가 합니다.
source.extension.vsixmanifest를 클릭 참조 추가
대화 상자에서 누릅니다 추가 페이로드 하 여 DSL의 VSIX 파일을 찾습니다.VSIX 파일 DSL 솔루션에서에 빌드됩니다 DslPackage\bin\*.
이 사용자가 DSL 및 확장을 동시에 설치할 수 있습니다.DSL 사용자를 이미 설치한 경우 확장만 설치 됩니다.
검토 하 고 업데이트 필드에 source.extension.vsixmanifest.클릭 버전 선택 확인 하 고 올바른 Visual Studio 버전으로 설정 합니다.
클래스 라이브러리 프로젝트에 코드를 추가 합니다.예제는 다음 단원에서 지침으로 사용 합니다.
다양 한 제스처를 명령과 유효성 검사 클래스를 추가할 수 있습니다.
키를 눌러 확장 테스트 합니다 F5.실험의 인스턴스에서 Visual Studio, 만들기 또는 DSL의 대 한 예제 파일을 엽니다.
MEF 확장에 대 한 Dsl 작성
어셈블리 코드를 별도 DSL 확장 솔루션의 프로젝트에서 확장을 작성할 수 있습니다.DSL의 일부로 명령과 제스처, 유효성 검사 코드를 작성 하는 편리한 방법으로 MEF에서 DslPackage 프로젝트를 사용할 수도 있습니다.
메뉴 명령
메뉴 명령을 작성 하려면 구현 하는 클래스를 정의 합니다. ICommandExtension 및 DSL에 라는 사용자 정의 속성을 가진 클래스 접두사 YourDslCommandExtension.여러 개의 메뉴 명령을 클래스를 작성할 수 있습니다.
QueryStatus()사용자가 다이어그램을 마우스 오른쪽 단추로 클릭할 때마다 호출 됩니다.현재 선택 영역을 검사 하 고 설정 해야 command.Enabled 명령을 적용할 수 있는 경우를 나타낼 수 있습니다.
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"; }
}
}
}
제스처 처리기
제스처 처리기 내부 또는 외부를 다이어그램으로 끌어다 원하는 위치에서 끌어 개체를 처리할 수 있습니다 Visual Studio.다음 예제에서는 파일 Windows 탐색기에서 다이어그램으로 끌 수가 있습니다.파일 이름이 들어 있는 요소를 만듭니다.
다른 DSL 모델 및 UML 모델의 끌으로 처리 하는 처리기를 작성할 수 있습니다.자세한 내용은 방법: 끌어서 놓기 처리기 추가를 참조하십시오.
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();
}
}
}
}
유효성 검사 제약 조건
유효성 검사 메서드가 표시 되어가 ValidationExtension DSL, 고도 생성 되는 특성이 ValidationMethodAttribute.메서드 특성에 의해 표시 되지 않은 모든 클래스에 나타날 수 있습니다.
자세한 내용은 도메인별 언어에서 유효성 검사를 참조하십시오.
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);
} } } }
참고 항목
개념
MEF(Managed Extensibility Framework)