規則傳播模型內的變更
您可以建立傳播變更從一個項目至另一個視覺效果,並建立模型的 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和DeleteRule網域關聯性。當項目或連結是即將被刪除時,就會觸發。直到交易結束後,[ModelElement.IsDeleting] 屬性為 true。
已刪除的項目或連結時,就會執行。所有其他規則所執行,包括 DeletingRules 之後,就會執行規則。ModelElement.IsDeleting,則為 false,就 ModelElement.IsDeleted,則為 true。若要以便進行後續的復原,此項目並不實際移除記憶體,但它會從 Store.ElementDirectory 中移除。
項目移到另一個儲存區的磁碟分割中。
(請注意這不與圖形的圖形的位置)。
此規則僅適用於網域關聯性。如果您明確地指派連結的任一端的模型項目,並觸發它項目。
使用 MoveBefore 或 MoveToIndex 方法在連結上的項目之間的連結順序變更時觸發。
當某交易建立時,就會執行。
當即將認可交易時,就會執行。
執行復原交易時。
每個類別都有您覆寫的方法。型別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();
}
}
}