本文来聊聊 WPF 那些值得称赞的设计中的 NamedObject 类型。在 WPF 中,有很多值得我学习的设计开发思想,其中就包括本文将要介绍的 NamedObject 类型。此类型的定义仅仅只是为了方便调试,而没有具体的业务功能

在 WPF 的 WindowsBase 程序集里面就定义了 WPF 的很多基础类型,例如咱都在用的 DependencyObject 等类型。本文的 NamedObject 也正是定义在 WindowsBase 程序集里面众多的类型之一,代码就放在 src\Microsoft.DotNet.Wpf\src\WindowsBase\MS\Internal\NamedObject.cs 文件里面

这是一个代码量很少的类型,如下面的内容,就是 NamedObject 的全部代码

    internal class NamedObject
{
public NamedObject(string name)
{
if (String.IsNullOrEmpty(name))
throw new ArgumentNullException(name); _name = name;
} public override string ToString()
{
if (_name[0] != '{')
{
// lazily add {} around the name, to avoid allocating a string
// until it's actually needed
_name = String.Format(CultureInfo.InvariantCulture, "{{{0}}}", _name);
} return _name;
} string _name;
}

按照 dotnet 里面的常用设计,咱的 ToString 方法大多数都是用来调试使用,或者序列化使用。而 NamedObject 类型没有序列化的需求,因此就剩下一个调试的功能了。可以看到 NamedObject 没有任何的属性定义,也没有任何的方法。实际除了调试以外,就和 object 对象是一个功能。其实这是对的,这就是专门用来辅助调试的类型

为什么需要定义 NamedObject 类型来做调试辅助?原因是在 WPF 中,有某些地方的逻辑需要用到一个空的 Object 对象,而此对象不是用来做类里面的内部锁的信息,此空对象将会在框架层传输。在框架层传输一个空的对象无疑会让开发者在调试时感觉到无从下手,原因其实和空异常差不多。假定在某个业务逻辑里面,收到了其他模块发生过来的一个非预期的对象,刚好这个对象是一个空的 object 对象,此时请问这个空的 object 对象是什么,是由哪个模块创建的

为了构建出一个稳固的 UI 框架,或者为了方便后续像我这样水平一般的开发者可以参与到框架的开发,古老的 WPF 框架开发大佬们就定义了 NamedObject 对象。如名字一样,这个类型仅仅只是一个带命名的 object 对象而已。但一个带命名的 object 对象就相当于给代码加上了单位,可以极大提升框架开发调试遇到一个空对象时了解这是由哪个模块创建的

如 NamedObject 被 DependencyProperty 使用时的例子,在 DependencyProperty 里面,如果咱有某个未定义的依赖属性,或者说在绑定或属性转换器里面失败时返回一个未定义的属性时,按照最佳实践,咱应该返回 DependencyProperty 的 UnsetValue 属性

在其他业务端或 WPF 框架内收到了一个 Object 的时候,如何可以了解到这是 DependencyProperty 的 UnsetValue 属性,而不是开发者用户在业务层自己创建的某个对象?假定咱的 DependencyProperty 的 UnsetValue 属性采用空 object 对象,那么意味着调试时需要通过 VisualStudio 的创建对象 Id 的功能,通过给 DependencyProperty 的 UnsetValue 属性创建 Id 才能通过 Id 判断对象是否相同

无疑,如果只有一次两次需要如此调试,那还可以。如果每次调试框架时都需要执行如上步骤,通过 VisualStudio 的创建对象 Id 的功能才能进行调试,那小心键盘被 WPF 框架开发者砸了

古老的 WPF 框架开发大佬们给 DependencyProperty 的 UnsetValue 属性的定义如下

   public static readonly object UnsetValue = new NamedObject("DependencyProperty.UnsetValue");

此时的优势在于当我拿到一个 object 对象的时候,可以在 VisualStudio 里面快速看到此对象是一个带命名的 DependencyProperty.UnsetValue 对象,此时就可以快速了解到此对象的创建者以及业务意图

值得我学习的是,不要轻易在对外公开的传递的对象,使用 object 对象,而是给此对象一个确切的定义类型。如果可以的话,再给这个确切的定义类型附加一句用来辅助调试的话,如 "DependencyProperty.UnsetValue" 这个字符串。这样可以方便在框架层进行调试时,了解传输的对象的创建者,以及开发者的意图

当前的 WPF 在 https://github.com/dotnet/wpf 完全开源,使用友好的 MIT 协议,意味着允许任何人任何组织和企业任意处置,包括使用,复制,修改,合并,发表,分发,再授权,或者销售。在仓库里面包含了完全的构建逻辑,只需要本地的网络足够好(因为需要下载一堆构建工具),即可进行本地构建

dotnet 读 WPF 源代码笔记 提升调试效率的 NamedObject 类型的更多相关文章

  1. dotnet 读 WPF 源代码笔记 布局时 Arrange 如何影响元素渲染坐标

    大家是否好奇,在 WPF 里面,对 UIElement 重写 OnRender 方法进行渲染的内容,是如何受到上层容器控件的布局而进行坐标偏移.如有两个放入到 StackPanel 的自定义 UIEl ...

  2. dotnet 读 WPF 源代码笔记 渲染收集是如何触发

    在 WPF 里面,渲染可以从架构上划分为两层.上层是 WPF 框架的 OnRender 之类的函数,作用是收集应用程序渲染的命令.上层将收集到的应用程序绘制渲染的命令传给下层,下层是 WPF 的 GF ...

  3. Vue学习笔记:提升开发效率和体验的常用工具

    Vetur 用途: 语法高亮 标签补全,模板生成 Lint检查 格式化 vs code环境配置文件 文件-->首选项-->搜索veture(找不到需要自行安装)-->在setting ...

  4. DirectX11 With Windows SDK--19 模型加载:obj格式的读取及使用二进制文件提升读取效率

    前言 一个模型通常是由三个部分组成:网格.纹理.材质.在一开始的时候,我们是通过Geometry类来生成简单几何体的网格.但现在我们需要寻找合适的方式去表述一个复杂的网格,而且包含网格的文件类型多种多 ...

  5. Atitit. 提升开发效率与质量DSL ( 3) ----实现DSL的方式总结

    Atitit. 提升开发效率与质量DSL ( 3) ----实现DSL的方式总结 1. 管道抽象 1 2. 层次结构抽象(json,xml etc) 1 3. 异步抽象promise 1 4. Ide ...

  6. atitit.提升开发效率---MDA 软件开发方式的革命(3)----自动化建表

    atitit.提升开发效率---MDA 软件开发方式的革命(3)----自动化建表 1. 建模在后自动建表 1 1. 传统上,需要首先建表,在业务编码.. 1 2. 模型驱动建表---更多简化法是在建 ...

  7. atitit.提升开发效率---mda 软件开发方式的革命--(2)

    atitit.提升开发效率---mda 软件开发方式的革命--(2) 1. 一个完整的MDA规范包含: 1 2. 一个完整的MDA应用程序包含: 1 3. MDA能够带来的最大的三个好处是什么? 2 ...

  8. 读Flask源代码学习Python--config原理

    读Flask源代码学习Python--config原理 个人学习笔记,水平有限.如果理解错误的地方,请大家指出来,谢谢!第一次写文章,发现好累--!. 起因   莫名其妙在第一份工作中使用了从来没有接 ...

  9. 《深入浅出WPF》笔记——绘画与动画

    <深入浅出WPF>笔记——绘画与动画   本篇将记录一下如何在WPF中绘画和设计动画,这方面一直都不是VS的强项,然而它有一套利器Blend:这方面也不是我的优势,幸好我有博客园,能记录一 ...

  10. atitit.提升研发效率的利器---重型框架与类库的区别与设计原则

    atitit.提升研发效率的利器---重型框架与类库的区别与设计原则 1. 框架的意义---设计的复用 1 1.1. 重型框架就是it界的重武器. 1 2. 框架 VS. 库 可视化图形化 1 2.1 ...

随机推荐

  1. 记录--微信调用jssdk--Invalid Signature, updateAppMessageShareData: denied等问题

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 最近在做安卓内嵌入H5活动页拉新活动,遇到的棘手问题记录下, 一是为了日后遇到同样问题好回顾,二是希望能帮到有同样问题的兄弟. 废话不多说 ...

  2. C++ Concurrency in Action 读书笔记三:并发操作的同步

    Chapter 4 并发操作的同步·Synchronizing concurrent operations

  3. Springboot Mybatis 全局变量使用

    application.properties中配置 mybatis.configuration.variables.k1='v1' mybatis.configuration.variables.k2 ...

  4. C# Mat Bitmap互转

    var mat = OpenCvSharp.Extensions.BitmapConverter.ToMat(source);//bitmap转mat Cv2.CvtColor(mat, mat, C ...

  5. C# 二维码生成、识别,去除白边、任意颜色

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...

  6. PS-AXI-GPIO-流水灯设计

    PS-AXI-GPIO-流水灯设计 1.实验目的 在了解了AXI协议的基本内容后,通过已经设计好的AXI的IP核来了解实际设计中AXI的工作原理和设计原理是必要的.这个实验以前实际上按照教程做过,但是 ...

  7. SpringBoot集成LDAP同步数据

    1.pom引入依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId& ...

  8. GID:旷视提出全方位的检测模型知识蒸馏 | CVPR 2021

    论文提出的GID框架能够自动选择可辨别目标用于知识蒸馏,而且综合了feature-based.relation-based和response-based知识,全方位蒸馏,适用于不同的检测框架中.从实验 ...

  9. Scala 可变列表ListBuffer

    1 package chapter07 2 3 import scala.collection.mutable.ListBuffer 4 5 object Test05_ListBuffer { 6 ...

  10. mybatis使用Hashmap传递参数

    mapper 1 <!--传递map的key --> 2 <insert id="addUser2" parameterType="map"& ...