Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
V sadě Visual And Modeling SDK (VMSDK) můžete vytvořit pravidlo úložiště, které rozšíří změnu z jednoho prvku do druhého. Když dojde ke změně libovolného prvku v úložišti, pravidla jsou naplánována ke spuštění, obvykle při potvrzení vnější transakce. Existují různé typy pravidel pro různé druhy událostí, například přidání prvku nebo jeho odstranění. Pravidla můžete připojit ke konkrétním typům prvků, obrazců nebo diagramů. Mnoho předdefinovaných funkcí je definováno pravidly: například pravidla zajišťují aktualizaci diagramu při změně modelu. Jazyk specifický pro doménu můžete přizpůsobit přidáním vlastních pravidel.
Pravidla úložiště jsou obzvláště užitečná pro šíření změn v úložišti – to znamená změny prvků modelu, relací, obrazců nebo spojnic a jejich vlastností domény. Pravidla se nespustí, když uživatel vyvolá příkazy Zpět nebo Znovu. Místo toho správce transakcí zajistí, že se obsah úložiště obnoví do správného stavu. Pokud chcete rozšířit změny do prostředků mimo úložiště, použijte události úložiště. Další informace naleznete v části Obslužné rutiny událostí a jejich šíření změn mimo model.
Předpokládejme například, že chcete určit, že pokaždé, když uživatel (nebo váš kód) vytvoří nový prvek typu ExampleDomainClass, další prvek jiného typu se vytvoří v jiné části modelu. Můžete napsat addRule a přidružit ho k ExampleDomainClass. V pravidle byste napsali kód pro vytvoření dalšího prvku.
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();
}
}
}
Poznámka:
Kód pravidla by měl změnit stav pouze prvků v úložišti; to znamená, že pravidlo by mělo změnit pouze prvky modelu, relace, obrazce, spojnice, diagramy nebo jejich vlastnosti. Pokud chcete aplikovat změny do prostředků mimo obchod, definujte Store Eventy. Další informace naleznete v tématu Obslužné rutiny událostí šíří změny mimo model.
Definování pravidla
Definujte pravidlo jako třídu s předponou atributu
RuleOn. Atribut přidruží pravidlo k jedné z vašich tříd domény, relací nebo prvků diagramu. Pravidlo se použije pro každou instanci této třídy, která může být abstraktní.Zaregistrujte si pravidlo tak, že ho přidáte do sady, kterou vrací
GetCustomDomainModelTypes()ve vaší třídě doménového modelu.Odvozujte třídu pravidla z jedné z abstraktní třídy Rule a napište kód metody provádění.
Následující části popisují tyto kroky podrobněji.
Definování pravidla pro třídu domény
V souboru vlastního kódu definujte třídu a předponu atributem RuleOnAttribute :
[RuleOn(typeof(ExampleElement), // Usual value - but required, because it is not the default: FireTime = TimeToFire.TopLevelCommit)] class MyRule ...Typ předmětu v prvním parametru může být doménová třída, vztah domény, obrazec, spojnice nebo diagram. Obvykle platí pravidla pro třídy domény a relace.
Obvykle je
FireTimeTopLevelCommit. Tím se zajistí, že se pravidlo spustí až po provedení všech primárních změn transakce. Alternativy jsou Inline, což spustí pravidlo brzy po změně; a LocalCommit, který provádí pravidlo na konci aktuální transakce (což nemusí být vnější). Můžete také nastavit prioritu pravidla tak, aby ovlivnila její řazení ve frontě, ale jedná se o nespolehlivý způsob dosažení požadovaného výsledku.Abstraktní třídu můžete zadat jako typ předmětu.
Pravidlo platí pro všechny instance třídy předmětu.
Výchozí hodnota
FireTimeje TimeToFire.TopLevelCommit. To způsobí, že se pravidlo spustí při potvrzení nejvzdálenější transakce. Alternativou je TimeToFire.Inline. To způsobí, že se pravidlo spustí brzy po aktivační události.
Zaregistrovat pravidlo
Přidejte třídu pravidla do seznamu typů vrácených modelem vaší domény
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(); } }Pokud si nejste jistí názvem vaší třídy doménového modelu, podívejte se do souboru Dsl\GeneratedCode\DomainModel.cs
Tento kód napište do vlastního souboru kódu v projektu DSL.
Napsání kódu pravidla
Odvodit třídu pravidla z jedné z následujících základních tříd:
Základní třída Spouštěč AddRule Přidán je prvek, odkaz nebo tvar.
Tato možnost slouží k detekci nových relací kromě nových prvků.ChangeRule Hodnota vlastnosti domény se změní. Argument metody poskytuje staré a nové hodnoty.
U obrazců se toto pravidlo aktivuje, když se předdefinovanáAbsoluteBoundsvlastnost změní, pokud se obrazec přesune.
V mnoha případech je pohodlnější přepsatOnValueChangedneboOnValueChangingv zpracovatelském modulu vlastností. Tyto metody se volají bezprostředně před a po změně. Naproti tomu pravidlo obvykle běží na konci transakce. Další informace naleznete v tématu Domain Property Value Change Handlers. Poznámka: Toto pravidlo se neaktivuje při vytvoření nebo odstranění odkazu. Místo toho napišteAddRuleaDeleteRulepro vztah domény.DeletingRule Aktivuje se, když se chystá odstranit prvek nebo odkaz. Vlastnost ModelElement.IsDeleting je true až do konce transakce. DeleteRule Provede se při odstranění prvku nebo propojení. Pravidlo se spustí po provedení všech ostatních pravidel, včetně pravidel mazání. ModelElement.IsDeleting je false a ModelElement.IsDeleted je true. Chcete-li povolit následné vrácení zpět, prvek není ve skutečnosti odebrán z paměti, ale je odebrán z Store.ElementDirectory. MoveRule Prvek se přesouvá z jednoho oddílu úložiště do jiného.
(Všimněte si, že to nesouvisí s grafickou polohou obrazce.)RolePlayerChangeRule Toto pravidlo platí jenom pro vztahy domén. Aktivuje se, pokud explicitně přiřadíte prvek modelu k některému konci propojení. RolePlayerPositionChangeRule Aktivuje se, když je řazení odkazů na prvek nebo z prvku změněno pomocí metod MoveBefore nebo MoveToIndex na odkazu. TransactionBeginningRule Provede se při vytvoření transakce. TransactionCommittingRule Bude vykonán, když se očekává, že transakce bude potvrzena. TransactionRollingBackRule Provede se, když se transakce chystá vrátit zpět. Každá třída má metodu, kterou přepíšete. Napište
overrideve své třídě, abyste to objevili. Parametr této metody identifikuje prvek, který se mění.Všimněte si následujících bodů o pravidlech:
Sada změn v transakci může aktivovat mnoho pravidel. Pravidla se obvykle provádějí při potvrzení nejkrajnější transakce. Jsou provedeny v nepředem stanoveném pořadí.
Pravidlo se vždy provádí uvnitř transakce. Proto nemusíte vytvářet novou transakci, aby bylo nutné provádět změny.
Pravidla se nespouštějí při vrácení transakce zpět nebo při provádění operací Zpět nebo Znovu. Tyto operace resetují veškerý obsah Storu do předchozího stavu. Proto pokud pravidlo změní stav čehokoli mimo Store, nemusí být synchronizovaný s obsahem Storu. Pokud chcete aktualizovat stav mimo Store, je lepší použít události. Další informace naleznete v tématu Obslužné rutiny událostí šíří změny mimo model.
Některá pravidla se spustí při načtení modelu ze souboru. Chcete-li zjistit, zda probíhá načítání nebo ukládání, použijte
store.TransactionManager.CurrentTransaction.IsSerializing.Pokud kód pravidla vytvoří více aktivačních událostí pravidla, přidají se na konec seznamu aktivací a spustí se před dokončením transakce. Odstraněné pravidla se spustí po všech ostatních pravidlech. Jedno pravidlo může v transakci běžet mnohokrát, jednou pro každou změnu.
Chcete-li předávat informace do pravidel a z pravidel, můžete ukládat informace do souboru
TransactionContext. Jedná se pouze o slovník, který se udržuje během transakce. Je zrušen při ukončení transakce. Argumenty události v jednotlivých pravidlech poskytují přístup k pravidlu. Mějte na paměti, že pravidla se nespouštějí v předvídatelném pořadí.Po zvážení jiných alternativ používejte pravidla. Pokud například chcete aktualizovat vlastnost při změně hodnoty, zvažte použití počítané vlastnosti. Pokud chcete omezit velikost nebo umístění obrazce, použijte .
BoundsRulePokud chcete odpovědět na změnu hodnoty vlastnosti, přidejte do vlastnosti obslužnouOnValueChangedrutinu. Další informace naleznete v tématu Reakce na a šíření změn.
Example
Následující příklad aktualizuje vlastnost při vytvoření instance relace domény pro propojení dvou prvků. Pravidlo se aktivuje nejen v případě, že uživatel vytvoří odkaz v diagramu, ale také v případě, že kód programu vytvoří odkaz.
Pokud chcete tento příklad otestovat, vytvořte DSL pomocí šablony řešení Tok úloh a vložte následující kód do souboru v projektu Dsl. Sestavte a spusťte řešení a otevřete ukázkový soubor v projektu ladění. Nakreslete odkaz na komentář mezi obrazcem Komentáře a prvkem toku. Text v komentáři se změní, aby zobrazil informace o nejnovějším prvku, ke kterému jste jej připojili.
V praxi byste obvykle napsali DeleteRule pro každou 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();
}
}
}