1

来自google,很多文章说DependencyProperty是静态的,因为它有一个KeyValue机制来维护对象的每个实例的值。

但问题是,如果我们针对 DependencyProperty 调用 GetValue / SetValue,它如何识别每个实例并生成密钥以便从 HashTable 中读取/保存对象的不同实例的值?

例如:如果我们创建 2 个 TestDp 实例,然后为两个实例的 TestDProperty 设置值,那么 SetValue 如何识别每个实例并将 DependencyProperty 值相应地保存到哈希表中?

我检查了 DependencyObject 的 GetValue 和 SetValue 的代码,但我仍然无法弄清楚它是如何区分每个实例的。代码 this.LookupEntry(dp.GlobalIndex) 将获取 EntryIndex 但我不确定如何生成 GlobalIndex 以区分对象的每个实例。

 public class TestDp : DependencyObject
    {
        protected static DependencyProperty dpTest = DependencyProperty.Register("TestDProperty", typeof(string), typeof(TestDp));
        public string TestDProperty
        {
            get
            {
                var r = (string)GetValue(dpTest);
                return r;
            }
            set
            {
                SetValue(dpTest, value);
            }
        }
    }
4

2 回答 2

1

The GetValue of DependencyObject will call GetValueEntry and consume the EntryIndex which you've mentioned. However, it doesn't seems to generate any key based on the instance information.

于 2014-11-04T13:47:01.360 回答
0

使用的缩写:

DP =DependencyProperty

dp# =DP 实例,例如 DP1

=DependencyObject

dp# =DO 实例

好问题,但我认为接受的答案和评论并没有真正得到你的要求,真可惜。一个更明确的问题可能是:

DependencyObject 实例如何存储其本地 DependencyProperty(s) 并通过 and 检索它(它们GetValueSetValue

根据您的描述,您正在编写方式探索出路,您应该做的是更多地追踪源代码:

依赖对象.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有两个属性:

  1. PropertyIndex: 正是特定 DP 实例的 GlobalIndex
  2. 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

于 2021-11-14T17:27:41.357 回答