규칙으로 모델 내부의 변경 내용 전파
시각화 및 모델링 SDK (VMSDK)에서 다른 요소에서 변경을 전파할 수 저장소 규칙을 만들 수 있습니다.모든 요소에는 저장소에 변경 될 때 규칙 일반적으로 가장 바깥쪽 트랜잭션이 커밋될 때 실행 되도록 예약 합니다.서로 다른 요소를 추가 또는 삭제와 같은 이벤트에 대 한 규칙입니다.요소, 도형 또는 다이어그램의 특정 형식에 규칙을 연결할 수 있습니다.다양 한 기본 제공 기능 규칙에 의해 정의 됩니다: 예를 들어, 규칙 모델을 변경 하면 다이어그램 업데이트 되었는지 확인 합니다.사용자 고유의 규칙을 추가 하 여 도메인 관련 언어를 사용자 지정할 수 있습니다.
규칙 저장소 저장소-즉, 내 변경 내용을 전파 모델 요소, 관계, 셰이프 또는 연결선 및 해당 도메인 등록 정보 변경에 특히 유용 합니다.사용자는 실행 취소 또는 다시 실행 명령을 호출 하는 경우 규칙을 실행 하지 않습니다.대신 트랜잭션 관리자 저장소 내용을 올바른 상태로 복원 되었는지 확인 합니다.저장소는 외부 리소스에 대 한 변경 내용을 전파 하려는 경우 저장 된 이벤트를 사용 합니다.자세한 내용은 이벤트 처리기로 모델 외부의 변경 내용 전파를 참조하십시오.
예를 들어, 사용자 (또는 코드) ExampleDomainClass 형식의 새 요소를 만들 때마다 다른 형식의 요소를 다른 모델의 다른 부분에 작성 되도록 지정 하려는 경우를 가정 합니다.Addrule가 작성 한 Exampledomainclass와 연관 시킬 수 있습니다.규칙에서 추가 요소를 만드는 코드를 작성 합니다.
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.Modeling;
namespace ExampleNamespace
{
// Attribute associates the rule with a domain class:
[RuleOn(typeof(ExampleDomainClass), FireTime=TimeToFire.TopLevelCommit)]
// The rule is a class derived from one of the abstract rules:
class MyAddRule : AddRule
{
// Override the abstract method:
public override void ElementAdded(ElementAddedEventArgs e)
{
base.ElementAdded(e);
ExampleDomainClass element = e.ModelElement;
Store store = element.Store;
// Ignore this call if we're currently loading a model:
if (store.TransactionManager.CurrentTransaction.IsSerializing)
return;
// Code here propagates change as required – for example:
AnotherDomainClass echo = new AnotherDomainClass(element.Partition);
echo.Name = element.Name;
echo.Parent = element.Parent;
}
}
// The rule must be registered:
public partial class ExampleDomainModel
{
protected override Type[] GetCustomDomainModelTypes()
{
List<Type> types = new List<Type>(base.GetCustomDomainModelTypes());
types.Add(typeof(MyAddRule));
// If you add more rules, list them here.
return types.ToArray();
}
}
}
[!참고]
코드 규칙을 상태 저장소 내에만 변경 해야 합니다. 즉, 규칙이 모델 요소, 관계, 도형, 연결선, 다이어그램 또는 해당 속성을 변경 해야 합니다.저장소는 외부 리소스에 대 한 변경 내용을 전파 하려는 경우 저장 된 이벤트를 정의 합니다.자세한 내용은 이벤트 처리기로 모델 외부의 변경 내용 전파를 참조하십시오.
규칙을 정의 하려면
클래스 앞에 규칙 정의 RuleOn 특성입니다.특성 규칙을 도메인 클래스, 관계, 또는 다이어그램의 요소 중 하나에 연결합니다.규칙에 추상 수 있습니다 하이 클래스의 모든 인스턴스에 적용 됩니다.
규칙에서 반환 하는 집합을 추가 하 여 등록 GetCustomDomainModelTypes() 도메인 모델 클래스에 있습니다.
규칙 클래스를 추상 규칙 클래스 중 하나에서 파생 하 고 메서드 실행의 코드를 작성 합니다.
다음 섹션에서는 이러한 단계에 자세히 설명합니다.
도메인 클래스에는 규칙을 정의 하려면
사용자 지정 코드 파일에서 클래스를 정의 하 고 앞의 RuleOnAttribute 특성:
[RuleOn(typeof(ExampleElement), // Usual value – but required, because it is not the default: FireTime = TimeToFire.TopLevelCommit)] class MyRule ...
주체 종류의 첫 번째 매개 변수는 도메인 클래스, 도메인 관계, 도형, 연결선, 또는 다이어그램 수 있습니다.일반적으로 도메인 클래스 및 관계에 규칙이 적용 됩니다.
The FireTime is usually TopLevelCommit.이렇게만 모든 주요 변경 트랜잭션 완료 한 규칙을 실행할 수 있습니다.있는 대체 규칙이 변경 된 후 바로 실행 하는 인라인 됩니다. 및 규칙 (있는 가장 바깥쪽 일 수 없는) 현재 트랜잭션 끝에 실행 하는 LocalCommit입니다.우선 순위 큐의 순서에 영향을 미치는 규칙을 설정할 수도 있습니다 있지만이 필요한 결과 달성 하는 불안정 한 방법이 됩니다.
추상 클래스는 주체 유형으로 지정할 수 있습니다.
규칙 제목 클래스의 모든 인스턴스에 적용 됩니다.
기본값은 FireTime TimeToFire.TopLevelCommit입니다.이렇게 가장 바깥쪽 트랜잭션이 수행 될 때 실행 되는 규칙이 됩니다.대신 TimeToFire.Inline 있습니다.이 규칙을 트리거하는 이벤트가 후 곧 실행할 수 됩니다.
규칙을 등록 하려면
규칙 클래스를 반환 하는 형식 목록에 추가 GetCustomDomainModelTypes 했습니다.
public partial class ExampleDomainModel { protected override Type[] GetCustomDomainModelTypes() { List<Type> types = new List<Type>(base.GetCustomDomainModelTypes()); types.Add(typeof(MyAddRule)); // If you add more rules, list them here. return types.ToArray(); } }
도메인 모델 클래스의 이름을 확인할 수 없는 경우 포함 된 파일 찾기Dsl\GeneratedCode\DomainModel.cs
DSL 프로젝트에 사용자 지정 코드 파일에이 코드를 작성 합니다.
규칙의 코드를 작성 하려면
규칙 클래스는 다음 기본 클래스 중 하나에서 파생 합니다.
기본 클래스
트리거
요소, 링크, 또는 셰이프 추가 됩니다.
이 대화 상자를 사용 하 여 새 요소 외에 새 관계를 검색 합니다.
도메인 속성 값이 변경 됩니다.메서드 인수는 이전 값과 새 값을 제공합니다.
도형에 대해이 규칙이 때 기본 제공 AbsoluteBounds 셰이프를 이동 하는 경우 속성 변경 합니다.
대부분의 경우 무시 하는 것이 더 편리할 수 OnValueChanged 또는 OnValueChanging 속성 처리기에서입니다.이러한 방법은 바로 전과 변경 후 호출 됩니다.그러나 규칙을 트랜잭션 끝에 일반적으로 실행 됩니다.자세한 내용은 도메인 속성 값 변경 처리기를 참조하십시오.
참고이 규칙에 대 한 링크를 만들거나 삭제 하는 경우 발생 하지 않습니다.대신 작성 된 AddRule a DeleteRule 도메인 관계에 대 한.요소 또는 링크 삭제 될 때 발생 합니다.ModelElement.IsDeleting 속성은 트랜잭션이 끝날 때까지 마찬가지입니다.
요소 또는 링크 삭제 될 때 수행 됩니다.다른 모든 규칙, Deletingrules을 포함 하 여 실행 한 후 규칙을 실행 합니다.Modelelement.isdeleting은 false입니다 및 ModelElement.IsDeleted 적용 됩니다.다음 실행 취소를 허용 하는 요소의 실제로 메모리에서 제거 되지 않습니다 하지만 store.elementdirectory에서 제거 됩니다.
요소 한 저장소 파티션에서 다른 위치로 이동 합니다.
(이 그래픽 도형의 위치에 관련 되지 않았습니다 있습니다.)
이 규칙은 도메인 관계에만 적용 됩니다.모델 요소에 대 한 링크의 양쪽 끝에 명시적으로 할당 하는 경우 발생 합니다.
요소에서 링크의 순서에 대 한 링크 MoveToIndex 또는 MoveBefore 메서드를 사용 하 여 변경 될 때 발생 합니다.
트랜잭션을 만들 때 실행 됩니다.
트랜잭션이 커밋된 할 때 실행 합니다.
트랜잭션을 다시 롤백됩니다 때 실행 합니다.
각 클래스 메서드를 재정의 하 여 있습니다.형식 override 에서 클래스를 검색 합니다.이 메서드의 매개 변수는 변경 되는 요소를 식별 합니다.
다음은 규칙에 대 한 확인 합니다.
트랜잭션에서 변경 내용 집합이 여러 규칙을 트리거할 수 있습니다.일반적으로 가장 바깥쪽 트랜잭션이 수행 될 때 규칙이 실행 됩니다.불특정된의 순서로 실행 됩니다.
항상 규칙은 트랜잭션 내에서 실행 됩니다.변경 내용을 적용 하려면 새 트랜잭션을 만들 필요가 없습니다.
규칙은 트랜잭션이 롤백됩니다 또는 실행 취소 또는 다시 실행 작업을 수행할 때 실행 되지 않습니다.이러한 작업은 저장소의 모든 내용을 이전 상태로 다시 설정합니다.규칙 안에 있는 저장소의 상태를 변경 하는 경우 따라서이 synchronism 저장소에 콘텐츠 두지 않을 수 있습니다.외부 저장소 상태를 업데이트 하려면 이벤트를 사용 하는 것이 더 좋습니다.자세한 내용은 이벤트 처리기로 모델 외부의 변경 내용 전파를 참조하십시오.
모델 파일에서 로드 될 때 몇 가지 규칙이 실행 됩니다.로드 하거나 저장 진행 중인지 여부를 확인 하려면 사용 하 여 store.TransactionManager.CurrentTransaction.IsSerializing.
자세한 규칙 트리거 규칙의 코드를 만드는 경우 발사 목록 끝에 추가 되 고 트랜잭션이 완료 되기 전에 실행 됩니다.DeletedRules 후 모든 규칙이 실행 됩니다.규칙이 트랜잭션의 각 변경에 대해 한 번에 여러 번 실행할 수 있습니다.
규칙의 정보를 전달 하려면 정보 저장소는 TransactionContext.이 트랜잭션 동안 유지 됩니다 사전입니다.트랜잭션이 종료 될 때 삭제 됩니다.각 규칙에는 이벤트 인수에 대 한 액세스를 제공합니다.규칙이 예상한 순서 대로 실행 해야 합니다.
다른 대안을 고려 한 후 규칙을 사용 합니다.예를 들어 속성 값을 변경할 때는 업데이트 하려면 계산된 된 속성을 사용 하십시오.크기 또는 위치 셰이프를 제한 하고자 하는 경우 사용 하는 BoundsRule.속성 값의 변경에 응답 하는 경우 추가 된 OnValueChanged 처리기의 속성.자세한 내용은 변경 내용에 대한 대응 및 전파를 참조하십시오.
예제
다음은 두 요소를 연결 하는 도메인 관계를 인스턴스화할 때 속성을 업데이트 합니다.프로그램 코드에 연결 하는 경우 뿐만 아니라 사용자의 다이어그램에도 연결 하면 규칙이 트리거되지.
이 예제를 테스트 하려면 만들기 작업 흐름 솔루션 템플릿을 사용 하 여 DSL 및 Dsl 프로젝트에서 파일에 다음 코드를 삽입 합니다.빌드하고 솔루션을 실행 하의 디버깅 프로젝트 예제 파일을 엽니다.주석 링크 메모 셰이프 사이의 흐름 요소를 그립니다.주석 변경 내용을 보고서에 연결 된 가장 최근에 사용한 요소의 텍스트입니다.
실제로 모든 Addrule의 Deleterule은 일반적으로 작성 합니다.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.Modeling;
namespace Company.TaskRuleExample
{
[RuleOn(typeof(CommentReferencesSubjects))]
public class RoleRule : AddRule
{
public override void ElementAdded(ElementAddedEventArgs e)
{
base.ElementAdded(e);
CommentReferencesSubjects link = e.ModelElement as CommentReferencesSubjects;
Comment comment = link.Comment;
FlowElement subject = link.Subject;
Transaction current = link.Store.TransactionManager.CurrentTransaction;
// Don't want to run when we're just loading from file:
if (current.IsSerializing) return;
comment.Text = "Flow has " + subject.FlowTo.Count + " outgoing connections";
}
}
public partial class TaskRuleExampleDomainModel
{
protected override Type[] GetCustomDomainModelTypes()
{
List<Type> types = new List<Type>(base.GetCustomDomainModelTypes());
types.Add(typeof(RoleRule));
return types.ToArray();
}
}
}