昨日、自分の DependencyProperty 作成クラスをテストしようとしたときに、同様の問題が発生しました。この質問に出くわし、依存関係プロパティを登録解除する実際の解決策がないことに気付きました。そこで、 Red Gate .NET Reflectorを使用して掘り下げて、何が思いつくかを調べました。
オーバーロードを見るとDependencyProperty.Register
、それらはすべて を指しているように見えましたDependencyProperty.RegisterCommon
。このメソッドには 2 つの部分があります。
まず、物件が既に登録されているかどうかを確認します
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.RegisteredPropertyList
が、ItemStructList<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 が依存関係プロパティを登録解除するための正式な方法を持たないことを選択した理由がある可能性が高く、それに逆らおうとする試みは単にトラブルを求めているだけです。