Reguły propagujące zmiany w modelu
Można utworzyć regułę magazynu propagowanie zmian z jednego elementu do innego w wizualizacji i modelowania SDK (VMSDK).W przypadku zmiany do dowolnego elementu w magazynie zasad są zaplanowane wykonywane zwykle, gdy peryferyjnych transakcja została zatwierdzona.Istnieją różne typy reguł dla różnych rodzajów zdarzeń, takich jak dodanie elementu lub usuwanie go.Reguły można dołączyć do określonych typów elementów, kształtów i diagramów.Wiele wbudowanych funkcji są zdefiniowane przez reguły: na przykład reguły zapewniają, że diagram jest aktualizowany po zmianie modelu.Język specyficzne dla domeny można dostosować, dodając własne reguły.
Zasady w magazynie są szczególnie przydatne, propagowanie zmian wewnątrz magazynu – to znaczy zmienia kolor na elementy modelu, relacje, kształty lub łączniki i ich domeny właściwości.Zasady nie są uruchamiane, gdy użytkownik wywołuje poleceń Cofnij i ponów.Zamiast tego Menedżer transakcji podejmuje się, że zawartość magazynu są przywracane do poprawnego stanu.Propagowanie zmian zasobów poza magazynu, należy użyć zdarzenia z przechowywać.Aby uzyskać więcej informacji, zobacz Programy obsługi zdarzeń propagujące zmiany poza modelem.
Na przykład załóżmy że chcesz określić, że w każdym przypadku, gdy użytkownik (lub kod) tworzy nowy element typu ExampleDomainClass, tworzony jest dodatkowy element innego typu w innej części modelu.Można napisać AddRule i skojarzyć ją z ExampleDomainClass.W regule, aby utworzyć dodatkowy element będzie napisać kod.
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();
}
}
}
[!UWAGA]
Kod reguły, należy zmienić stan elementów wewnątrz magazynu; oznacza to, że reguły, należy zmienić tylko elementy modelu, relacje, kształtów, łączniki, diagramy lub ich właściwości.Propagowanie zmian zasobów poza magazynu, należy zdefiniować przechowywania zdarzeń.Aby uzyskać więcej informacji zobaczProgramy obsługi zdarzeń propagujące zmiany poza modelem
Aby zdefiniować regułę
Zdefiniować regułę jako klasa z prefiksem RuleOn atrybut.Atrybut kojarzy regułę jednej z klas domeny, relacje lub elementów diagramu.Reguła będzie stosowana do każdego wystąpienia tej klasy, które mogą być abstrakcyjne.
Zarejestrować reguła przez dodanie go do zestawu zwrócony przez GetCustomDomainModelTypes() w klasie modelu domeny.
Pochodzić z klasy reguły z jednej klasy abstrakcyjne reguły i napisać kod metody realizacji.
W poniższych sekcjach opisano te kroki bardziej szczegółowo.
Aby zdefiniować regułę, w klasie domeny
W pliku kodu niestandardowego, zdefiniowanie klasy i z prefiksem RuleOnAttribute atrybut:
[RuleOn(typeof(ExampleElement), // Usual value – but required, because it is not the default: FireTime = TimeToFire.TopLevelCommit)] class MyRule ...
Typ podmiotu w pierwszym parametrze może być klasa domeny, relacji domeny, kształt, łącznika lub diagramu.Zwykle stosować zasady do klas domeny i relacje.
The FireTime is usually TopLevelCommit.Gwarantuje to, że reguła jest wykonywany tylko, po przeprowadzeniu podstawowego zmiany transakcji.Alternatywą jest w tekście, który wykonuje regułę wkrótce po zmianie; i LocalCommit, która wykonuje regułę na końcu bieżącej transakcji (który może nie być peryferyjnych).Można również ustawić priorytet reguły wpływać na kolejność w kolejce, ale jest to metoda zawodne osiągnięcia wyników, które są wymagane.
Klasa abstrakcyjna można określić jako typ podmiotu.
Reguła będzie stosowana do wszystkich wystąpień klasy tematu.
Wartość domyślna dla FireTime jest TimeToFire.TopLevelCommit.Powoduje to, że reguły, które mają być wykonane podczas peryferyjnych transakcja została zatwierdzona.Alternatywą jest TimeToFire.Inline.Powoduje to, że reguły mają być wykonane, wkrótce po wyzwalającego zdarzenie.
Aby zarejestrować reguły
Dodać klasę regułę do listy typów zwrócony przez GetCustomDomainModelTypes w modelu domeny:
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(); } }
Jeśli nie jesteś pewien nazwy klasy modelu domeny, Szukaj plikuDsl\GeneratedCode\DomainModel.cs
Napisać ten kod w pliku kodu niestandardowego w projekcie DSL.
Aby napisać kod reguły
Pochodną klasy reguły jedną z następujących klas podstawowych:
Klasa podstawowa
Wyzwalacz
Dodaje się element, łącze lub kształt.
Służy do wykrywania nowych stosunków, oprócz nowych elementów.
Wartość właściwości domeny zostanie zmieniona.Argument metody udostępnia wartości stare i nowe.
Dla kształtów, zasada ta zostanie wywołany podczas wbudowanych AbsoluteBounds zmiany właściwości, jeśli kształt jest przenoszony.
W wielu przypadkach jest bardziej wygodne zastąpić OnValueChanged lub OnValueChanging w obsłudze właściwości.Metody te są nazywane bezpośrednio przed i po zmianie.Z drugiej strony reguła jest uruchamiana zazwyczaj na koniec transakcji.Aby uzyskać więcej informacji, zobacz Obsługa zmian wartości właściwości domeny.
[!UWAGA]
Ta reguła nie zostanie wywołany, gdy łącze jest tworzone lub usuwane.Zamiast pisać AddRule i DeleteRule dla relacji domeny.
Wyzwalane, gdy element lub łącze jest do usunięcia.Właściwość ModelElement.IsDeleting jest true do zakończenia transakcji.
Wykonywane, gdy element lub łącze zostało usunięte.Reguła jest wykonywany po zostały wykonane wszystkie inne zasady, łącznie z DeletingRules.ModelElement.IsDeleting ma wartość false, a ModelElement.IsDeleted ma wartość true.Aby umożliwić późniejsze Cofnij, element nie jest usuwany z pamięci, ale jest ona usuwana z Store.ElementDirectory.
Element jest przenoszony z partycji z jednego magazynu do innego.
(Należy zauważyć, że nie jest to związane z graficznego położenie kształtu).
Ta reguła dotyczy tylko relacje między domenami.Jeśli element modelu jawnie przypisać do jednego z końców łącze jest wyzwalany.
Wyzwalane, gdy kolejność łączy do lub z elementu zostanie zmieniona przy użyciu metody MoveBefore lub MoveToIndex na łączu.
Wykonywane, gdy transakcja jest tworzona.
Wykonywane, gdy transakcja ma być zatwierdzane.
Wykonywane, gdy transakcja ma być wycofana.
Każda klasa ma metodę, który można zastąpić.Typ override w klasie je wykryje.Parametr tej metody identyfikuje element, który został zmieniony.
Zwróć uwagę następujące kwestie dotyczące zasad:
Zestaw zmian w transakcji może wyzwolić wiele reguł.Zazwyczaj zasady są wykonywane, gdy peryferyjnych transakcja została zatwierdzona.Są one wykonywane w nieokreślonej kolejności.
Reguła jest zawsze wykonywana wewnątrz transakcji.W związku z tym nie trzeba utworzyć nową transakcję, aby wprowadzić zmiany.
Zasady nie są wykonywane, gdy transakcja jest cofana lub gdy wykonywane są operacje Cofnij i ponów.Te operacje Resetuj zawartość magazynu do poprzedniego stanu.W związku z tym jeśli reguła zmienia stan niczego poza magazynu, to może nie przechowywać w synchronism z magazynem zawartości.Aby zaktualizować stan poza magazynu, jest lepiej jest użyć zdarzenia.Aby uzyskać więcej informacji, zobacz Programy obsługi zdarzeń propagujące zmiany poza modelem.
Niektóre reguły są wykonywane, gdy model jest ładowany z pliku.Aby ustalić, czy ładowanie lub zapisywanie jest w toku, użyj store.TransactionManager.CurrentTransaction.IsSerializing.
Jeśli kod reguła tworzy więcej reguły wyzwalaczy, zostanie dodany na końcu listy wypalania i zostanie wykonana przed zakończeniem transakcji.DeletedRules są wykonywane po wszystkich innych reguł.Jedną regułę można uruchamiać wiele razy w transakcji, jeden raz dla każdej zmiany.
Aby przekazać informacje do i z zasady, można przechowywać informacje w TransactionContext.Jest to po prostu słownik jest utrzymywane podczas transakcji.Jest on usuwany po zakończeniu transakcji.Argumenty zdarzeń w każdej regule zapewniają dostęp do niego.Należy pamiętać, że zasady nie są wykonywane w ustalonym porządku.
Użyj reguł, po rozważeniu innych alternatyw.Rozważmy na przykład jeśli chcesz zaktualizować właściwości, gdy zmiany wartości, przy użyciu właściwości obliczeniowych.Jeśli chcesz ograniczyć rozmiar lub położenie kształtu, użyj BoundsRule.Aby odpowiedzieć na zmianę wartości właściwości, dodać OnValueChanged obsługi do właściwości.Aby uzyskać więcej informacji, zobacz Odpowiadanie na zmiany i propagowanie zmian.
Przykład
Poniższy przykład aktualizuje właściwość, kiedy relacji domeny jest połączyć dwa elementy.Reguła zostanie wyzwolony nie tylko w przypadku, gdy użytkownik tworzy łącze na diagramie, ale także, jeśli kod program tworzy łącze.
Aby przetestować ten przykład, utworzyć DSL, przy użyciu szablonu zadania przepływu roztworu i wstawić następujący kod w pliku w programie project Dsl.Budowanie i uruchomić roztworu i otworzyć przykładowy plik w programie project debugowanie.Narysuj łącza komentarz między kształtem komentarz, a element przepływu.Tekst zmiany komentarza w sprawozdanie na temat najnowszych element połączyły się.
W praktyce byłoby zwykle napisać DeleteRule dla każdego AddRule.
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();
}
}
}