規則傳播模型內的變更

您可以建立傳播變更從一個項目至另一個視覺效果,並建立模型的 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();
   }
 }
}
注意事項注意事項

規則的程式碼應該變更的狀態只存放 ; 區內的項目 也就是只模型項目、 關聯性、 圖形、 連接器、 圖表或其屬性,應該變更該規則。如果您想要將變更傳播到存放區外的資源,定義儲存的事件。如需詳細資訊,請參閱事件處理常式傳播模型外的變更

若要定義規則

  1. 定義規則,如類別做為前置詞與RuleOn屬性。與您的網域類別、 關聯性或圖表元素的其中一個屬性產生關聯的規則。規則將套用至每個執行個體,這個類別,它可能是抽象。

  2. 註冊規則,將文件新增到集合所傳回的GetCustomDomainModelTypes()在您的網域模型類別。

  3. 衍生規則類別其中一個抽象的規則類別中,並且撰寫程式碼的執行方法。

下列章節會說明這些步驟的細節。

若要在網域類別上定義的規則

  • 在自訂程式碼檔案中,定義一個類別,並在它前面加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 專案中的自訂程式碼檔案。

撰寫規則的程式碼

  • 規則從衍生類別的其中一個下列的基底類別:

    基底類別

    觸發程序

    AddRule

    新增項目]、 [連結] 或 [圖形。

    使用此選項來偵測新的關聯性,除了新的項目。

    ChangeRule

    網域屬性值已變更。方法引數提供新舊值。

    此規則就會觸發圖形,當內建AbsoluteBounds屬性的變更,如果圖形移動。

    在許多情況下,會比較方便覆寫OnValueChanged或OnValueChanging屬性處理常式中。立即之前和之後的變更,會呼叫這些方法。相反地,此規則通常執行交易的結尾。如需詳細資訊,請參閱 網域屬性值變更處理常式

    注意事項注意事項
    當您建立或刪除連結時,並不會觸發這項規則。相反地,寫入AddRule和DeleteRule網域關聯性。

    DeletingRule

    當項目或連結是即將被刪除時,就會觸發。直到交易結束後,[ModelElement.IsDeleting] 屬性為 true。

    DeleteRule

    已刪除的項目或連結時,就會執行。所有其他規則所執行,包括 DeletingRules 之後,就會執行規則。ModelElement.IsDeleting,則為 false,就 ModelElement.IsDeleted,則為 true。若要以便進行後續的復原,此項目並不實際移除記憶體,但它會從 Store.ElementDirectory 中移除。

    MoveRule

    項目移到另一個儲存區的磁碟分割中。

    (請注意這不與圖形的圖形的位置)。

    RolePlayerChangeRule

    此規則僅適用於網域關聯性。如果您明確地指派連結的任一端的模型項目,並觸發它項目。

    RolePlayerPositionChangeRule

    使用 MoveBefore 或 MoveToIndex 方法在連結上的項目之間的連結順序變更時觸發。

    TransactionBeginningRule

    當某交易建立時,就會執行。

    TransactionCommittingRule

    當即將認可交易時,就會執行。

    TransactionRollingBackRule

    執行復原交易時。

  • 每個類別都有您覆寫的方法。型別override在您探索它的類別。這個方法的參數會識別正在變更的項目。

請注意下列幾點相關規則:

  1. 在交易中的變更集可能觸發許多的規則。通常,最外層的交易已認可時,所執行的規則。它們會在未指定的順序執行。

  2. 規則一定是在交易內執行。因此,您不必建立新的交易,才能變更。

  3. 當復原交易,或復原或取消復原作業,不會執行規則。這些作業會重設成先前的狀態的存放區的所有內容。因此,如果您的規則變更任一項目的外部存放區的狀態,它可能會保留在存放區的 synchronism 內容。若要更新存放區外的狀態,最好是使用事件。如需詳細資訊,請參閱 事件處理常式傳播模型外的變更

  4. 從檔案載入模型時,會執行一些規則。如果要判斷載入或儲存是否正在進行中,請使用store.TransactionManager.CurrentTransaction.IsSerializing。

  5. 如果您的統治的程式碼會建立多個規則的引動程序,它們將會加入至清單的結尾引發,並在交易完成之前會先執行。DeletedRules 會在所有其他規則後執行。一項規則可以執行許多次,在交易中,每次變更一次。

  6. 若要通過規則的資訊,您可以儲存中的資訊TransactionContext。不過這只是字典,其交易期間都會保持。當交易結束時,它會處置。每個規則中的事件引數提供給它的存取。請記住可預測的順序不會執行規則。

  7. 使用規則之後在考慮其他替代方案。比方說,如果您想要更新的屬性值變更時,請考慮使用計算的屬性。如果您要限制的大小或位置的圖形,請使用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();
    }
  }

}

請參閱

概念

事件處理常式傳播模型外的變更

BoundsRules 限制圖案位置和大小