任何方式向联合国登记册WPF依赖的财产?
-
02-07-2019 - |
题
我跑进一个不寻常的问题在我的单元的测试。类我是检测创建了一个依赖性的动态是在运行时间和类型的依赖性可能会有所不同,具体取决于该情况。虽然写我的单元的测试,我需要建立依赖性的不同类型和导致错误,因为你不能重新定义现有依赖性。
因此,是否有任何方法对联合国寄存器的依赖性或更改类型的现有依赖性的财产?
谢谢!
OverrideMetadata()只可以让你改变了很少的东西喜欢默认值,所以它不是有帮助的。程序域做法是一个很好的想法和可能的工作,但似乎更加复杂比我真的很想深入探讨为单元的测试。
我从来没有找到一种方法取消注册的依赖酒店所以我还是没有和仔细地重新组织我的单元的测试,以避免的问题。我得到一位小测试的复盖范围,但由于这个问题将永远不会发生在一个实际的应用程序,只有在单元的测试我可以住它。
谢谢你的帮助!
解决方案
我在昨天尝试测试自己的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.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可能有理由选择不采用正式方式取消注册依赖项属性,并试图反对它只是在寻找麻烦。
其他提示
如果其他一切都失败了,您可以为每个测试创建一个新的AppDomain。
我认为您不能取消注册依赖项属性,但您可以通过覆盖这样的元数据来重新定义它:
MyDependencyProperty.OverrideMetadata(typeof(MyNewType),
new PropertyMetadata());
如果我们为这样的标签注册名称:
Label myLabel = new Label();
this.RegisterName(myLabel.Name, myLabel);
我们可以使用以下方法轻松取消注册名称:
this.UnregisterName(myLabel.Name);
我面临的情况,我创建了一个自定义的控制,继承了 Selector
这意味着该视图可以有两个属性, HorizontalItemsSource
和 VerticalItemsSource
.
我甚至不使用获取定性,并不要使用户能够进行访问。
所以我阅读 statenjason是伟大的回答, 和它给了我一个巨大的POV关于如何消除一DP。
然而,我的问题是,由于我宣布 ItemsSourceProperty
成员和 ItemsSource
作为 Private Shadows
(private new
C#),我不能载在设计时间,因为使用 MyControlType.ItemsSourceProperty
会提到的阴影的变量。
还有,在采用循环中提到的是enswer上述(foreach DictionaryEntry
等等), 我有一个异常扔说,收集有改变过的迭代。
因此,我想出了一个稍微不同的方法那里的DependencyProperty是hardcodedly称在运行,并收集被复制到阵列,所以它不是改变(VB.NET对不起):
Dim dpType = GetType(DependencyProperty)
Dim bFlags = BindingFlags.NonPublic Or BindingFlags.Static
Dim FromName =
Function(name As String, ownerType As Type) DirectCast(dpType.GetMethod("FromName",
bFlags).Invoke(Nothing, {name, ownerType}), DependencyProperty)
Dim PropertyFromName = DirectCast(dpType.GetField("PropertyFromName", bFlags).
GetValue(Nothing), Hashtable)
Dim dp = FromName.Invoke("ItemsSource", GetType(DimensionalGrid))
Dim entries(PropertyFromName.Count - 1) As DictionaryEntry
PropertyFromName.CopyTo(entries, 0)
Dim entry = entries.Single(Function(e) e.Value Is dp)
PropertyFromName.Remove(entry.Key)
重要说明: 上述代码是所有的环绕在共同的构造的定义控制,我不需要检查是否是注册的,因为我知道,一个子类的Selcetor并提供, ItemsSource
dp。
有一个问题与ContentPresenter与不同Datatemplates其中一个他们中的有一个DependencyProperty与PropertyChangedCallback 当改变ContentPresenters内容来另一个数据模板回调仍然存在。
在UserControls卸的事件,我呼吁:
BindingOperations.ClearAllBindings(this);
Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Normal, new DispatcherOperationCallback(delegate { return null; }), null);
这为我工作