任何方式取消注册一个WPF依赖属性? [英] Any way to un-register a WPF dependency property?

查看:200
本文介绍了任何方式取消注册一个WPF依赖属性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我运行到一个不同寻常的问题,在我的单元测试。我测试的类在运行时动态地创建一个依赖属性,而依赖属性的类型可以根据具体情况而有所不同。在写我的单元测试,我需要建立不同​​类型的依赖属性,而导致错误,因为你不能重新定义现有的依赖属性。

I'm running into an unusual problem in my unit tests. The class I'm testing creates a dependency property dynamically at runtime and the type of that dependency property can vary depending on the circumstances. While writing my unit tests, I need to create the dependency property with different types and that leads to errors because you can't redefine an existing dependency property.

那么,有没有办法要么注销依赖财产或更改现有的依赖属性的类型?

So is there any way to either un-register a dependency property or to change the type of an existing dependency property?

谢谢!

OverrideMetadata()只允许你改变很少像默认值,所以它是没有帮助的。在AppDomain的做法是一个好主意,可能会奏效,但似乎比我真的很想钻研,为了单元测试更为复杂。

OverrideMetadata() only lets you change a very few things like default value so it isn't helpful. The AppDomain approach is a good idea and might work but seems more complicated than I really wanted to delve into for the sake of unit testing.

我从来没有找到一个方法来注销一个依赖属性,所以我踢,精心改编我的单元测试,以避免这一问题。我越来越少了几分测试覆盖范围,但由于这个问题将永远不会发生在实际应用中,只在单元测试中,我可以忍受。

I never did find a way to unregister a dependency property so I punted and carefully reorganized my unit tests to avoid the issue. I'm getting a bit less test coverage, but since this problem would never occur in a real application and only during unit testing I can live with it.

感谢您的帮助!

推荐答案

我昨天刚有类似的问题,想测试自己的DependencyProperty创建类时。我碰到这个问题,发现并没有真正解决注销依赖属性。所以,我没有使用红门.net反射的,看看我能想出一些挖。

I had similar issue just yesterday when trying to test my own DependencyProperty creating class. I came across this question, and noticed there was no real solution to unregister dependency properties. So I did some digging using Red Gate .NET Reflector to see what I could come up with.

纵观 DependencyProperty.Register 过载,他们似乎都指向 DependencyProperty.RegisterCommon 。该方法有两个部分:

Looking at the DependencyProperty.Register overloads, they all seemed to point to DependencyProperty.RegisterCommon. That method has two portions:

首先要检查属性已经被注册

First to check if the property is already registered

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

二,注册的DependencyProperty

Second, Registering the 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> ,但还没有看到它被使用。不过,为了安全,我想我会尝试从删除,以及如果可能的话。

Both pieces center around DependencyProperty.PropertyFromName, a HashTable. I also noticed the DependencyProperty.RegisteredPropertyList, an ItemStructList<DependencyProperty> but have not seen where it is used. However, for safety, I figured I'd try to remove from that as well if possible.

所以,我结束了以下code,让我注销一个依赖属性。

So I wound up with the following code that allowed me to "unregister" a dependency property.

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异常。不过,我强烈建议您,不以任何形式的生产code使用。有可能是一个原因,MSFT选择不具有正式的方式注销依赖属性,并尝试去反对它只是自寻烦恼。

It worked well enough for me to run my tests without getting an "AlreadyRegistered" exception. However, I strongly recommend that you do not use this in any sort of production code. There is likely a reason that MSFT chose not to have a formal way to unregister a dependency property, and attempting to go against it is just asking for trouble.

这篇关于任何方式取消注册一个WPF依赖属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆