有什么方法可以取消注册WPF依赖属性?

Sco*_*ger 9 .net wpf dependency-properties

我在单元测试中遇到了一个不寻常的问题.我正在测试的类在运行时动态创建依赖项属性,并且该依赖项属性的类型可以根据具体情况而变化.在编写单元测试时,我需要创建具有不同类型的依赖项属性,这会导致错误,因为您无法重新定义现有的依赖项属性.

那么有没有办法取消注册依赖属性或更改现有依赖属性的类型?

谢谢!


OverrideMetadata()只允许您更改默认值等极少数内容,因此无效.AppDomain方法是一个好主意,可能会工作,但似乎比我真正想要深入研究单元测试更复杂.

我从未找到取消注册依赖项属性的方法,因此我进行了细分并仔细重新组织了单元测试以避免出现问题.我的测试覆盖率要低一些,但是因为这个问题永远不会发生在真正的应用程序中,只有在单元测试期间才能使用它.

谢谢您的帮助!

sta*_*son 8

我昨天尝试测试自己的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 }));
  }
}
Run Code Online (Sandbox Code Playgroud)

第二,注册DependencyProperty

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

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

HatsTable是两个中心DependencyProperty.PropertyFromName.我也注意到了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);
}
Run Code Online (Sandbox Code Playgroud)

它运行良好,我可以运行我的测试,而不会得到"AlreadyRegistered"异常.但是,我强烈建议您不要在任何类型的生产代码中使用它.可能有一个原因,MSFT选择不采用正式方式取消注册依赖属性,并试图反对它只是在寻找麻烦.