使用的缩写:
DP =DependencyProperty
dp# =DP 实例,例如 DP1
做=DependencyObject
dp# =DO 实例
好问题,但我认为接受的答案和评论并没有真正得到你的要求,真可惜。一个更明确的问题可能是:
DependencyObject 实例如何存储其本地 DependencyProperty(s) 并通过 and 检索它(它们GetValue
)SetValue
?
根据您的描述,您正在编写方式探索出路,您应该做的是更多地追踪源代码:
依赖对象.SetValue
依赖对象.GetValue
在深入研究细节之前,请记住依赖机制提供的优势之一是有助于减少内存占用。所以你可以大致想象一下它是如何工作的:一开始,每个 DO 实例的本地 DP 为零;一旦通过调用 based 设置了本地 DP SetValue
,它就会在内存中分配一些空间来存储它。虽然描述与事实相去甚远,但至少给了你一个初步的把握。
依赖属性
首先,让我们关注DP。我们知道,每个 DP实例只会注册一次,并且 DP 有一个私有静态字段int GlobalIndexCount
,每注册一个新的 DP 实例,该字段就会增加 1。因此,每个 DP实例都有一个GlobalIndex
,一个可能的例子可能是:
DP 实例 |
全球指数 |
dp1 |
0 |
dp2 |
1 |
dp3 |
2 |
DP 的当前静态字段 GlobalIndexCount |
3(将分配给下一个注册的 DP 实例) |
顺便说一句,所有 DP 实例都由它维护,Hashtable PropertyFromName
这也是 class 的静态字段DependencyProperty
。请记住,每个 DP 类只实例化一次。
依赖对象
其次,让我们看看DO。每个 DO 实例维护一个数组:private EffectiveValueEntry[] _effectiveValues;
它存储它需要的所有本地DP 实例。EffectiveValueEntry
有两个属性:
PropertyIndex
: 正是特定 DP 实例的 GlobalIndex
Value
: DP 的本地值SetValue
假设我们有一个 DO 类定义如下:
// Keep declaration only and omit trivial code
public class MyDependencyObject : DependencyObject
{
protected static DependencyProperty Test1Property;
protected static DependencyProperty Test2Property;
protected static DependencyProperty Test3Property;
}
MyDependencyObject do1...;
do1.Test1 = 1;
do1.Test3 = 3;
MyDependencyObject do2...;
do2.Test2 = 2;
现在看起来像_effectiveValues
这样do1
EntryIndex.Index |
PropertyIndex(相当于 DP 的 GlobalIndex),已排序 |
价值 |
描述 |
0 |
0 |
1 |
Test1Property 的本地值 |
1 |
2 |
3 |
Test3Property 的本地值 |
你提到EntryIndex
的函数返回的位置。LookupEntry
对于do2中的情况:
入口指数 |
PropertyIndex(相当于 DP 的 GlobalIndex),已排序 |
价值 |
0 |
1 |
Test2Property 的本地值 |
所有EffectiveValueEntry
存储的_effectiveValues
都按GlobalIndex
关键点
现在到了你的难题的核心:当一个DO实例试图获取一个DP时,它使用DPGlobalIndex
搜索它的私有字段_effectiveValues
,如果找到,则返回一个本地DP值;否则,返回默认值或继承值。实际上,真实的故事要复杂得多,请参阅价值解决策略。
当谈到写作而不是阅读时,类似的故事也会发生,只是不是阅读而是修改_effectiveValues
。