加入收藏 | 设为首页 | 会员中心 | 我要投稿 安卓应用网 (https://www.0791zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 程序设计 > 正文

WPF基础到企业应用系列7――深入剖析依赖属性(六)

发布时间:2020-05-23 07:08:32 所属栏目:程序设计 来源:互联网
导读:十五. 模拟依赖属性实现 古人有”不入虎穴焉得虎子“的名句,我们今天也试着入一入虎穴,探探依赖属性里面到底藏着什么不可告人的秘密,在往下讲之前,我们先来看一下DependencyObject 、DependencyProperty 以及PropertyMetadata到底包含哪些功能,如下面三

十五. 模拟依赖属性实现

  古人有”不入虎穴焉得虎子“的名句,我们今天也试着入一入虎穴,探探依赖属性里面到底藏着什么不可告人的秘密,在往下讲之前,我们先来看一下DependencyObject 、DependencyProperty 以及PropertyMetadata到底包含哪些功能,如下面三幅图

WPF基础到企业应用系列7――深入剖析依赖属性(六)

WPF基础到企业应用系列7――深入剖析依赖属性(六)

WPF基础到企业应用系列7――深入剖析依赖属性(六)

  通过前面三幅图,我们就可以了解WPF依赖属性系统的大体结构以及主要功能,再者通过前面我们对它的使用,对它的内部实现也有一个相对比较清晰 的认识,那么接下来要做的就是:借助Reflector+VS调试内部代码功能一起来研究其内部的实现原理。 本来想详细写清楚开发的过程,但是有点多,所以我打算直接讲这几个类。大家也可以通过这个思路来试一试,同时还可以参考Mono的源码、WF的依赖属性源 码等。这里要推荐的是周永恒的博客,此人对技术的理解很是透彻,博文虽少,但每篇都堪称经典,所以他的文章,我都通读三遍。虽然大多概念都懂,并且读到深 处也能产生共鸣,其最主要目的还是学习他这种”阐述问题的思路“,后来也和此人MSN聊过几次。所以这个依赖属性的框架在某些程度上也借鉴了他的一些写 法。

  有了前面的思路,首先定义DependencyProperty这个类,它里面存储前面我们提到希望抽出来的字段。DependencyProperty内部维护了一个全局的Map用来储存所有的DependencyProperty,对外暴露了一个Register方法用来注册新的DependencyProperty。当然,为了保证在Map中键值唯一,注册时需要根据传入的名字和注册类的的 HashCode取异或来生成Key。 所以我们就可以完成DependencyProperty类了,代码如下,介绍详见代码注释。:

public sealed class DependencyProperty
{ //全局的IDictionary用来储存所有的DependencyProperty
internal static IDictionary<int,DependencyProperty> properties = new Dictionary<int,175);">DependencyProperty>(); //存储元数据的集合
private List<PropertyMetadata> _metadataMap = new PropertyMetadata>(); private static int globalIndex = 0; private PropertyMetadata def_metadata; private bool attached; private string name; private int _index; private Type owner_type; private Type property_type; private Type validator_type; // 构造函数
private DependencyProperty() { } //构造函数私有,保证外界不会对它进行实例化
private DependencyProperty(string name,175);">Type propertyType,175);">Type ownerType,175);">PropertyMetadata defaultMetadata) { this.name = name; property_type = propertyType; owner_type = ownerType; def_metadata = defaultMetadata; } // 常用属性
public PropertyMetadata DefaultMetadata { get { return def_metadata; } } public bool IsAttached { get { return attached; } } public int Index { get { return _index; } set { _index = value; } } public string Name { get { return name; } } public Type OwnerType { get { return owner_type; } } public Type PropertyType { get { return property_type; } } public Type ValidatorType { get { return validator_type; } } public override int GetHashCode() { return name.GetHashCode() ^ owner_type.GetHashCode(); } //注册依赖属性
public static DependencyProperty Register(string name,175);">Type ownerType) { return Register(name,propertyType,ownerType,new PropertyMetadata()); } //注册的公用方法,把这个依赖属性加入到IDictionary的键值集合中,Key为name和owner_type的GetHashCode取异,Value就是我们注册的DependencyProperty
public static PropertyMetadata defaultMetadata) { DependencyProperty property = new DependencyProperty(name,defaultMetadata); globalIndex++; property.Index = globalIndex; if (properties.ContainsKey(property.GetHashCode())) { throw new InvalidOperationException("A property with the same name already exists"); } //把刚实例化的DependencyProperty添加到这个全局的IDictionary种
properties.Add(property.GetHashCode(),property); return property; } //注册只读依赖属性
public static DependencyProperty RegisterReadOnly(string name,175);">PropertyMetadata typeMetadata) { DependencyProperty property = Register(name,typeMetadata); return property; } //注册附加依赖属性
public static DependencyProperty RegisterAttached(string name,175);">Type ownerType) { return RegisterAttached(name,175);">PropertyMetadata(),null); } public static PropertyMetadata defaultMetadata) { return RegisterAttached(name,defaultMetadata,175);">PropertyMetadata defaultMetadata,175);">Type validatorType) { true; property.validator_type = validatorType; return property; } //子类继承重写以及其他需要重写Metadata的时候使用
public void OverrideMetadata(Type forType,175);">PropertyMetadata metadata) { metadata.Type = forType; _metadataMap.Add(metadata); } //获取元数据信息
public PropertyMetadata GetMetadata(Type type) { PropertyMetadata medatata = _metadataMap.FirstOrDefault((i) => i.Type == type) ?? _metadataMap.FirstOrDefault((i) => type.IsSubclassOf(i.Type)); if (medatata == null) { medatata = def_metadata; } return medatata; } }

  有了DependencyProperty ,那么接下来就需要定义DependencyObject 来使用这个DependencyProperty 。首先使用DependencyProperty .Register方法注册了一个新的DependencyProperty ,然后提供了GetValue和SetValue两个方法来操作刚刚构造的DependencyProperty 。这个时候我们看到一个简单的依赖属性系统已初见端倪了,详见代码注释。

namespace Realize_DPs
{
    public abstract class DependencyObject :  IDisposable
{ //添加一个List来记录修改信息
private EffectiveValueEntry> _effectiveValues = new EffectiveValueEntry>(); //属性包装器,通过它来访问依赖属性
public object GetValue(DependencyProperty dp) { //首先通过判断是否改动过,以此来决定是读元数据的默认值还是改动了的值
EffectiveValueEntry effectiveValue = _effectiveValues.FirstOrDefault((i) => i.PropertyIndex == dp.Index); if (effectiveValue.PropertyIndex != 0) { return effectiveValue.Value; } else
{ PropertyMetadata metadata; metadata = DependencyProperty.properties[dp.GetHashCode()].DefaultMetadata; return metadata.DefaultValue; } } //属性包装器,通过它来设置依赖属性的值
public void SetValue(DependencyProperty dp,object value) { //首先通过判断是否改动过,以及改动过,则继续对改动过的元素赋值,否则对_effectiveValues增加元素
EffectiveValueEntry effectiveValue = _effectiveValues.FirstOrDefault((i) => i.PropertyIndex == dp.Index); if (effectiveValue.PropertyIndex != 0) { effectiveValue.Value = value; } else
{ effectiveValue = new EffectiveValueEntry() { PropertyIndex = dp.Index,Value = value }; _effectiveValues.Add(effectiveValue); } } public void Dispose() { //暂时还没有处理
} } internal struct EffectiveValueEntry
{ internal int PropertyIndex { get; set; } internal object Value { get; set; } } }

(编辑:安卓应用网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读