Dot-Net

有什麼方法可以取消註冊 WPF 依賴屬性?

  • February 9, 2018

我在單元測試中遇到了一個不尋常的問題。我正在測試的類在執行時動態創建一個依賴屬性,並且該依賴屬性的類型可能會因情況而異。在編寫單元測試時,我需要創建具有不同類型的依賴屬性,這會導致錯誤,因為您無法重新定義現有的依賴屬性。

那麼有沒有辦法取消註冊依賴屬性或更改現有依賴屬性的類型?

謝謝!


OverrideMetadata() 只允許您更改很少的內容,例如預設值,因此它沒有幫助。AppDomain 方法是一個好主意,並且可能有效,但似乎比我真正想為了單元測試而深入研究的要復雜。

我從來沒有找到取消註冊依賴屬性的方法,所以我小心翼翼地重新組織了我的單元測試以避免這個問題。我得到的測試覆蓋率要少一些,但是由於這個問題永遠不會在實際應用程序中發生,而且只有在單元測試期間我才能忍受它。

謝謝您的幫助!

我昨天在嘗試測試我自己的 DependencyProperty 創建類時遇到了類似的問題。我遇到了這個問題,並註意到沒有真正的解決方案來取消註冊依賴屬性。所以我使用Red Gate .NET Reflector進行了一些探勘,看看我能想出什麼。

看著DependencyProperty.Register過載,他們似乎都指向DependencyProperty.RegisterCommon。該方法有兩個部分:

首先檢查房產是否已經註冊

FromNameKey key = new FromNameKey(name, ownerType);
lock (Synchronized)
{
 if (PropertyFromName.Contains(key))
 {
   throw new ArgumentException(SR.Get("PropertyAlreadyRegistered", 
     new object[] { name, ownerType.Name }));
 }
}

二、註冊DependencyProperty

DependencyProperty dp = 
 new DependencyProperty(name, propertyType, ownerType, 
   defaultMetadata, validateValueCallback);

defaultMetadata.Seal(dp, null);
//...Yada yada...
lock (Synchronized)
{
 PropertyFromName[key] = dp;
}

兩個部分都DependencyProperty.PropertyFromName以 HashTable 為中心。我還注意到 , DependencyProperty.RegisteredPropertyListItemStructList<DependencyProperty>但沒有看到它在哪裡使用。但是,為了安全起見,我想如果可能的話,我也會嘗試從中刪除。

所以我結束了下面的程式碼,它允許我“取消註冊”一個依賴屬性。

private void RemoveDependency(DependencyProperty prop)
{
 var registeredPropertyField = typeof(DependencyProperty).
   GetField("RegisteredPropertyList", BindingFlags.NonPublic | BindingFlags.Static);
 object list = registeredPropertyField.GetValue(null);
 var genericMeth = list.GetType().GetMethod("Remove");
 try
 {
   genericMeth.Invoke(list, new[] { prop });
 }
 catch (TargetInvocationException)
 {
   Console.WriteLine("Does not exist in list");
 }

 var propertyFromNameField = typeof(DependencyProperty).
   GetField("PropertyFromName", BindingFlags.NonPublic | BindingFlags.Static);
 var propertyFromName = (Hashtable)propertyFromNameField.GetValue(null);

 object keyToRemove = null;
 foreach (DictionaryEntry item in propertyFromName)
 {
   if (item.Value == prop)
     keyToRemove = item.Key;
 }
 if (keyToRemove != null)
 propertyFromName.Remove(keyToRemove);
}

它工作得很好,我可以執行我的測試而不會出現“AlreadyRegistered”異常。但是,我強烈建議您**不要在任何類型的生產程式碼中使用它。**MSFT 選擇不使用正式的方式來取消註冊依賴項屬性可能是有原因的,而試圖違背它只是自找麻煩。

引用自:https://stackoverflow.com/questions/146794