建議使用 Visual Studio 2017

定義鎖定原則來建立唯讀區段

 

發行︰ 2016年6月

如需 Visual Studio 2017 的最新文件請參閱 Visual Studio 2017 文件

不變性 API Visual Studio Visualization and Modeling SDK 可讓程式鎖定部分或全部的定義域專屬語言 (DSL) 模型,讓它可以讀取但不是會變更。 無法使用這個唯讀選項,例如,讓使用者可以要求同事加上註解,並檢閱 DSL 模型,但可以變更原始禁止。

另外,當作者的 DSL,您可以定義鎖定原則。 鎖定的原則會定義哪些鎖定會允許、 不允許,或強制。 比方說,當您發行 DSL,您可以鼓勵協力廠商開發人員可以擴充,以新命令。 不過,您也可以使用鎖定原則,以防止變更模型的指定組件的唯讀狀態。

System_CAPS_ICON_note.jpg 注意

可以使用反映來規避鎖定原則。 協力廠商開發人員,提供清楚的界限,但不會提供強大的安全性。

詳細資訊和範例,位於Visual Studio Visualization and Modeling SDK網站。

在存放區、 磁碟分割或個別的項目,您可以設定鎖定。 例如,這個陳述式會防止模型項目遭到刪除,並避免變更也會讓其屬性︰

using Microsoft.VisualStudio.Modeling.Immutability; ...  
element.SetLocks(Locks.Delete | Locks.Property);  

其他鎖定值可用來避免變更關聯性、 建立項目、 資料分割和角色中的順序重新連結之間移動。

鎖定套用使用者動作和程式碼。 如果程式碼嘗試進行變更,InvalidOperationException就會擲回。 復原或重做作業的鎖定會遭到忽略。

您可以探索項目是否有任何鎖定在給定的一組使用IsLocked(Locks),您可以使用,以取得目前資料集的項目上的鎖定GetLocks()

您可以設定鎖定,而不使用交易。 鎖定資料庫不是存放區的一部分。 如果鎖定回應變更值的設定存放區中,例如在 OnValueChanged,您就應該允許復原作業的變更。

這些方法是擴充方法中所定義的Microsoft.VisualStudio.Modeling.Immutability命名空間。

鎖定資料分割和存放區

也可以套用鎖定資料分割和存放區。 設定磁碟分割的鎖定套用至資料分割中的所有項目。 因此,例如,下列陳述式會避免資料分割中的所有項目被刪除,無論他們自己的鎖定狀態。 不過,其他鎖定例如Locks.Property仍無法設定個別項目上︰

partition.SetLocks(Locks.Delete);  

設定存放區的鎖定適用於所有項目,而不論該資料分割和項目鎖定的設定為何。

使用鎖定

您可以使用鎖定來實作結構描述,如下列範例︰

  • 不允許所有的項目和關聯性,除了代表註解的變更。 這可讓使用者加註模型,而不變更它。

  • 不允許變更在預設的資料分割,但在圖表的資料分割允許變更。 使用者可以重新排列圖表中,但無法變更基礎模型。

  • 不允許變更除了在個別的資料庫中註冊的使用者群組的存放區。 其他使用者,將圖表和模型處於唯讀狀態。

  • 不允許變更模型,如果圖表的布林值屬性設定為 true。 提供功能表命令來變更該屬性。 這有助於確保它們不會進行的使用者不小心變更。

  • 允許加入和刪除的項目和關聯性的特定類別,但允許屬性變更。 這可讓使用者可以在其中填入屬性的固定表單。

鎖定可以設定存放區、 磁碟分割或個別 ModelElement 上。 鎖定是Flags列舉型別︰ 您可以結合使用其值 ' |'。

  • 鎖定的 ModelElement 一定要包含其資料分割的鎖定。

  • 鎖定資料分割一定要包含存放區的鎖定。

無法在磁碟分割上設定鎖定,或儲存和同時停用個別的項目上的鎖定。

這表示如果IsLocked(Value)為 true
沒有限制。
屬性無法變更網域屬性的項目。 這並不適用於網域中的類別關聯性的角色所產生的屬性。
新增在資料分割,則無法建立新的項目和連結,或儲存。

不適用ModelElement
Move無法分割區之間移動項目,如果element.IsLocked(Move)為 true,或者如果targetPartition.IsLocked(Move)為 true。
刪除無法刪除項目,如果這個鎖定設定項目本身,或任何的項目刪除會傳播,例如內嵌的項目和圖形。

您可以使用element.CanDelete()來探索項目是否可以刪除。
重新排列無法變更在 roleplayer 連結的順序。
RolePlayer無法變更的連結是來源為這個項目集。 比方說,新項目不可以內嵌在此項目。 這不會影響此元素的目標的連結。

如果這個項目是連結,其來源和目標都不會影響。
全部其他值的位元 OR 運算。

您可以定義 DSL 的作者,鎖定原則。 鎖定原則,讓您可以防止特定鎖定設定,或強制規定,必須設定特定的鎖定會節制主控 SetLocks() 的操作。 一般而言,您可使用鎖定原則防止使用者或開發人員不小心 contravening DSL 的用途,您可以宣告變數的相同方式private

您也可以使用鎖定原則設定視項目的型別上的所有項目鎖定。 這是因為SetLocks(Locks.None)一定項目第一次建立或從檔案還原序列化時呼叫。

不過,您無法使用原則來變更它的存留期期間的項目上的鎖定。 若要達成該效果,您應該使用呼叫SetLocks()

若要定義鎖定原則,您必須︰

  • 建立類別,實作ILockingPolicy

  • 加入這個類別都是透過您的 DSL DocData 的服務。

定義鎖定原則

ILockingPolicy具有下列定義︰

public interface ILockingPolicy  
{  
  Locks RefineLocks(ModelElement element, Locks proposedLocks);  
  Locks RefineLocks(Partition partition, Locks proposedLocks);  
  Locks RefineLocks(Store store, Locks proposedLocks);  
}  

若要進行呼叫時,會呼叫這些方法SetLocks()存放區、 磁碟分割或 ModelElement 上。 在每個方法中,您會提供一組建議的鎖定。 您可以傳回建議的設定,或您可以加入和減去鎖定。

例如:

using Microsoft.VisualStudio.Modeling;  
using Microsoft.VisualStudio.Modeling.Immutability;  
namespace Company.YourDsl.DslPackage // Change  
{  
  public class MyLockingPolicy : ILockingPolicy  
  {  
    /// <summary>  
    /// Moderate SetLocks(this ModelElement target, Locks locks)  
    /// </summary>  
    /// <param name="element">target</param>  
    /// <param name="proposedLocks">locks</param>  
    /// <returns></returns>  
    public Locks RefineLocks(ModelElement element, Locks proposedLocks)  
    {  
      // In my policy, users can never delete an element,  
      // and other developers cannot easily change that:  
      return proposedLocks | Locks.Delete);  
    }  
    public Locks RefineLocks(Store store, Locks proposedLocks)  
    {  
      // Only one user can change this model:  
      return Environment.UserName == "aUser"   
           ? proposedLocks : Locks.All;  
    }  
  

若要確定使用者隨時都可以刪除項目,即使其他程式碼呼叫SetLocks(Lock.Delete):

return proposedLocks & (Locks.All ^ Locks.Delete);

不允許在每個項目的 MyClass 的所有屬性的變更︰

return element is MyClass ? (proposedLocks | Locks.Property) : proposedLocks;

若要為服務使用您的原則

在您DslPackage專案中,加入新的檔案,其中包含與下列範例類似的程式碼︰

using Microsoft.VisualStudio.Modeling;  
using Microsoft.VisualStudio.Modeling.Immutability;  
namespace Company.YourDsl.DslPackage // Change  
{   
  // Override the DocData GetService() for this DSL.  
  internal partial class YourDslDocData // Change  
  {  
    /// <summary>  
    /// Custom locking policy cache.  
    /// </summary>  
    private ILockingPolicy myLockingPolicy = null;  
  
    /// <summary>  
    /// Called when a service is requested.  
    /// </summary>  
    /// <param name="serviceType">Service requested</param>  
    /// <returns>Service implementation</returns>  
    public override object GetService(System.Type serviceType)  
    {  
      if (serviceType == typeof(SLockingPolicy)   
       || serviceType == typeof(ILockingPolicy))  
      {  
        if (myLockingPolicy == null)  
        {  
          myLockingPolicy = new MyLockingPolicy();  
        }  
        return myLockingPolicy;  
      }  
      // Request is for some other service.  
      return base.GetService(serviceType);  
    }  
}  

顯示: