이벤트 처리기로 모델 외부의 변경 내용 전파

시각화 및 모델링 SDK에서 저장소 외부의 리소스(예: 비 저장소 변수, 파일, 다른 저장소의 모델 또는 기타 Visual Studio 확장)에 변경 내용을 전파하는 저장소 이벤트 처리기를 정의할 수 있습니다. 저장소 이벤트 처리기는 트리거 이벤트가 발생한 트랜잭션이 종료된 후에 실행됩니다. 실행 취소 또는 다시 실행 작업에서도 실행됩니다. 따라서 저장소 규칙과 달리 저장소 이벤트는 저장소 외부에 있는 값을 업데이트하는 데 가장 유용합니다. .NET 이벤트와 달리 저장소 이벤트 처리기는 클래스를 수신하도록 등록됩니다. 각 인스턴스에 대해 별도의 처리기를 등록할 필요가 없습니다. 변경 내용을 처리하는 다양한 방법 중에서 선택하는 자세한 내용은 변경 내용에 대한 대응 및 전파를 참조하세요.

그래픽 화면 및 기타 사용자 인터페이스 컨트롤은 저장소 이벤트에서 처리할 수 있는 외부 리소스의 예입니다.

저장소 이벤트를 정의하려면

  1. 모니터링할 이벤트 유형을 선택합니다. 전체 목록은 EventManagerDirectory의 속성을 참조하세요. 각 속성은 이벤트의 유형에 해당합니다. 가장 자주 사용되는 이벤트 유형은 다음과 같습니다.

    • ElementAdded - 모델 요소, 관계 링크, 도형 또는 연결선을 만들 때 트리거됩니다.

    • ElementPropertyChanged - Normal 도메인 속성 값이 변경될 때 트리거됩니다. 이 이벤트는 새 값과 이전 값이 같지 않은 경우에만 트리거됩니다. 계산된 스토리지 속성 및 사용자 지정 스토리지 속성에는 이벤트를 적용할 수 없습니다.

      관계 링크에 해당하는 역할 속성에는 적용할 수 없습니다. 대신, ElementAdded를 사용하여 도메인 관계를 모니터링합니다.

    • ElementDeleted - 모델 요소, 관계, 도형 또는 연결선이 삭제된 후에 트리거됩니다. 요소의 속성 값에 계속 액세스할 수 있지만 다른 요소와의 관계는 없습니다.

  2. DslPackage 프로젝트의 별도 코드 파일에 YourDslDocData에 대한 부분 클래스 정의를 추가합니다.

  3. 다음 예제와 같이 이벤트의 코드를 메서드로 작성합니다. DocData에 액세스하려는 경우가 아니면 이것은 static일 수 있습니다.

  4. 처리기를 등록하려면 OnDocumentLoaded()를 재정의합니다. 둘 이상의 처리기가 있는 경우 모두 동일한 장소에 등록할 수 있습니다.

등록 코드의 위치는 중요하지 않습니다. DocView.LoadView()는 대체 위치입니다.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.Modeling;

namespace Company.MusicLib
{
  partial class MusicLibDocData
  {
    // Register store events here or in DocView.LoadView().
    protected override void OnDocumentLoaded()
    {
      base.OnDocumentLoaded(); // Don't forget this.

      #region Store event handler registration.
      Store store = this.Store;
      EventManagerDirectory emd = store.EventManagerDirectory;
      DomainRelationshipInfo linkInfo = store.DomainDataDirectory
          .FindDomainRelationship(typeof(ArtistAppearsInAlbum));
      emd.ElementAdded.Add(linkInfo,
          new EventHandler<ElementAddedEventArgs>(AddLink));
      emd.ElementDeleted.Add(linkInfo,
          new EventHandler<ElementDeletedEventArgs>(RemoveLink));

      #endregion Store event handlers.
    }

    private void AddLink(object sender, ElementAddedEventArgs e)
    {
      ArtistAppearsInAlbum link = e.ModelElement as ArtistAppearsInAlbum;
      if (link != null)
            ExternalDatabase.Add(link.Artist.Name, link.Album.Title);
    }
    private void RemoveLink(object sender, ElementDeletedEventArgs e)
    {
      ArtistAppearsInAlbum link = e.ModelElement as ArtistAppearsInAlbum;
      if (link != null)
            ExternalDatabase.Delete(link.Artist.Name, link.Album.Title);
    }
  }
}

이벤트를 사용하여 스토어에서 실행 취소 가능한 조정을 수행

이벤트 처리기가 트랜잭션 커밋 후 실행되기 때문에 저장소 이벤트는 일반적으로 저장소 내에서 변경 내용을 전파하는 데 사용되지 않습니다. 대신 저장소 규칙을 사용합니다. 자세한 내용은 규칙으로 모델 내에서 변경 내용 전파를 참조하세요.

그러나 사용자가 원래 이벤트와 별도로 추가 업데이트를 실행 취소할 수 있도록 하려면 이벤트 처리기를 사용하여 저장소에 대한 추가 업데이트를 만들 수 있습니다. 예를 들어 소문자가 앨범 제목의 일반적인 규칙이라고 가정합니다. 사용자가 대문자로 입력한 제목을 소문자로 수정하는 저장소 이벤트 처리기를 작성할 수 있습니다. 그러나 사용자가 실행 취소 명령을 사용하여 수정을 취소하고 대문자를 복원할 수 있습니다. 두 번째 실행 취소는 사용자의 변경 내용을 제거합니다.

이와 대조적으로 동일한 작업을 수행하는 저장소 규칙을 작성한 경우, 사용자의 변경 내용과 규칙에 의한 수정 사항이 동일한 트랜잭션에 있으므로 사용자는 원래 변경 내용을 잃지 않고서는 조정을 실행 취소할 수 없습니다.

partial class MusicLibDocView
{
    // Register store events here or in DocData.OnDocumentLoaded().
    protected override void LoadView()
    {
      /* Register store event handler for Album Title property. */
      // Get reflection data for property:
      DomainPropertyInfo propertyInfo =
        this.DocData.Store.DomainDataDirectory
        .FindDomainProperty(Album.TitleDomainPropertyId);
      // Add to property handler list:
      this.DocData.Store.EventManagerDirectory
        .ElementPropertyChanged.Add(propertyInfo,
        new EventHandler<ElementPropertyChangedEventArgs>
             (AlbumTitleAdjuster));

      /*
      // Alternatively, you can set one handler for
      // all properties of a class.
      // Your handler has to determine which property changed.
      DomainClassInfo classInfo = this.Store.DomainDataDirectory
           .FindDomainClass(typeof(Album));
      this.Store.EventManagerDirectory
          .ElementPropertyChanged.Add(classInfo,
        new EventHandler<ElementPropertyChangedEventArgs>
             (AlbumTitleAdjuster));
       */
      return base.LoadView();
    }

// Undoable adjustment after a property is changed.
// Method can be static since no local access.
private static void AlbumTitleAdjuster(object sender,
         ElementPropertyChangedEventArgs e)
{
  Album album = e.ModelElement as Album;
  Store store = album.Store;

  // We mustn't update the store in an Undo:
  if (store.InUndoRedoOrRollback
      || store.InSerializationTransaction)
      return;

  if (e.DomainProperty.Id == Album.TitleDomainPropertyId)
  {
    string newValue = (string)e.NewValue;
    string lowerCase = newValue.ToLowerInvariant();
    if (!newValue.Equals(lowerCase))
    {
      using (Transaction t = store.TransactionManager
            .BeginTransaction("adjust album title"))
      {
        album.Title = lowerCase;
        t.Commit();
      } // Beware! This could trigger the event again.
    }
  }
  // else other properties of this class.
}

저장소 업데이트 이벤트를 작성하는 경우:

  • 실행 취소에서 모델 요소에 대한 변경 내용이 손실되지 않도록 store.InUndoRedoOrRollback을 사용합니다. 트랜잭션 관리자는 저장소의 모든 항목을 원래 상태로 다시 설정합니다.

  • 모델이 파일에서 로드되는 동안 변경되지 않도록 store.InSerializationTransaction을 사용합니다.

  • 변경 내용이 있을 경우 추가 이벤트가 트리거됩니다. 무한 루프가 발생하지 않도록 하세요.

저장소 이벤트 유형

각 이벤트 유형은 Store.EventManagerDirectory의 컬렉션에 해당합니다. 이벤트 처리기는 언제든 추가 또는 제거할 수 있지만, 문서가 로드될 때 이러한 처리기를 추가하는 것이 일반적입니다.

EventManagerDirectory 속성 이름 실행 시기
ElementAdded 도메인 클래스, 도메인 관계, 도형, 연결선 또는 다이어그램의 인스턴스가 만들어집니다.
ElementDeleted 모델 요소가 저장소의 요소 디렉터리에서 제거되어 더 이상 관계의 소스 또는 대상이 아닙니다. 요소는 실제로 메모리에서 삭제되지 않지만 이후 실행 취소의 경우 유지됩니다.
ElementEventsBegun 외부 트랜잭션의 끝에서 호출됩니다.
ElementEventsEnded 다른 모든 이벤트가 처리되면 호출됩니다.
ElementMoved 모델 요소가 한 저장소 파티션에서 다른 저장소 파티션으로 이동되었습니다.

이는 다이어그램에서 도형의 위치와는 관련이 없습니다.
ElementPropertyChanged 도메인 속성의 값이 변경되었습니다. 이전 값과 새 값이 같지 않은 경우에만 실행됩니다.
RolePlayerChanged 관계의 두 역할(end) 중 하나가 새 요소를 참조합니다.
RolePlayerOrderChanged 다중성이 1보다 큰 역할에서 링크 시퀀스가 변경되었습니다.
TransactionBeginning
TransactionCommitted
TransactionRolledBack

참고 항목

텍스트 템플릿 변환 구성 요소는 Visual Studio 확장 개발 워크로드의 일부로 자동으로 설치됩니다. Visual Studio 설치 프로그램의 개별 구성 요소 탭, SDK, 라이브러리, 프레임워크 범주 아래에서 설치할 수도 있습니다. 개별 구성 요소 탭에서 Modeling SDK 구성 요소를 설치합니다.