使用的缩写:
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。