我的第一个 Object Visitor

预演准备

为了顺利的进行测试,你需要确保本地已经安装了以下这些必备的软件:

  • dotnet 2.1 或者以上版本的 SDK,我们更建议直接安装 dotnet 5 SDK。下载地址:https://dotnet.microsoft.com/download
  • 安装一个趁手的 .net IDE。本演示过程将会使用 Visual Studio Code 作为基础演示 IDE。你也可以选择 Rider 或者 Visual Studio 来完成。

创建测试项目

我们需要一个测试项目来演示如何创建一个属于你的第一个 Object Visitor。

首先,确保本地已经正确安装了 dotnet 2.1 或者以上版本的 sdk,你可以运行以下命令来确认当前安装的版本:

dotnet --info

然后,随便找一个你喜欢的文件夹,运行以下命令来创建用于演示的测试控制台程序:

dotnet new console

最后,继续运行以下命令来安装最新的 Newbe.ObjectVisitor 工具包:

dotnet add package newbe.objectvisitor

这样,用于测试的项目就创建完成了。

创建一个简单的数据模型

我们使用 IDE 打开刚刚创建的项目,添加一个简单的数据模型类 OrderInfo :

public class OrderInfo
{
public int OrderId { get; set; }
public string Buyer { get; set; }
public decimal TotalPrice { get; set; }
}

实现一个拼接所有属性的逻辑

我们在 Program.cs 中添加以下代码来完成这些逻辑:

  1. new 一个 OrderInfo order
  2. 使用 StringBuilder 将 order 的所有属性名称和值拼接在一起
  3. 输出最后的 string
using System;
using System.Text;

namespace yueluo_dalao_yes
{
class Program
{
static void Main(string[] args)
{
var order = new OrderInfo
{
OrderId = 1,
Buyer = "yueluo",
TotalPrice = 62359.1478M
};
var sb = new StringBuilder();
sb.AppendFormat("{0}: {1}{2}", nameof(order.OrderId), order.OrderId, Environment.NewLine);
sb.AppendFormat("{0}: {1}{2}", nameof(order.Buyer), order.Buyer, Environment.NewLine);
sb.AppendFormat("{0}: {1}{2}", nameof(order.TotalPrice), order.TotalPrice, Environment.NewLine);
Console.WriteLine(sb.ToString());
}
}

public class OrderInfo
{
public int OrderId { get; set; }
public string Buyer { get; set; }
public decimal TotalPrice { get; set; }
}
}

我们使用以下命令来运行写好的逻辑:

dotnet run

就会得到以下这样的结果:

OrderId: 1
Buyer: yueluo
TotalPrice: 62359.1478

使用 Object Visitor 再次实现上面的逻辑

我们通过 Newbe.ObjectVisitor 来一样实现上面的逻辑:

  1. 使用 V() 扩展方法来创建一个 Object Visitor
  2. 调用 Object Visitor 的 ForEach 方法来注册 Visit 过程的行为
  3. 运行创建好的 Object Visitor
using System;
using System.Text;

namespace yueluo_dalao_yes
{
class Program
{
static void Main(string[] args)
{
var order = new OrderInfo
{
OrderId = 1,
Buyer = "yueluo",
TotalPrice = 62359.1478M
};

var sb2 = new StringBuilder();
var visitor = order.V()
.ForEach((name, value) => sb2.AppendFormat("{0}: {1}{2}", name, value, Environment.NewLine));
visitor.Run();
Console.WriteLine(sb2.ToString());
}
}

public class OrderInfo
{
public int OrderId { get; set; }
public string Buyer { get; set; }
public decimal TotalPrice { get; set; }
}
}

运行这个代码,你将会得到和上一节相同的结果。

那这么做究竟带来了什么好处?

首先,使用 Object Visitor 可以动态的适应模型类的变化,这点好处非常明显。

当 OrderInfo 中的属性增加时,“拼接部分” 的代码可以不用变化,实现动态的适配。

另外,还有一些好处是本示例没有体现的,将会在后续的文档中进行介绍:

  1. 它的运行效率很高。根据已有的基准测试,其性能表征和直接硬编码差距很小。
  2. 可以使用丰富的方式来对需要访问的属性进行多种方式过滤,例如:基于 Attribute 的过滤。
  3. 有了这种方式之后可以很轻松的扩展出基于对象属性的其他功能,例如:对象的属性验证(FluentValidation),对象的映射(AutoMapper)和对象的比较(Comparer)。

那这和直接使用反射有什么区别?

使用反射来实现以上的效果也是可以的,但相较来说,Object Visitor 的实现方式在性能方面根据优势:

  1. 根据已有的基准测试,Object Visitor 基于表达式树实现,其运行效率要比直接使用反射相关的读写方法高出许多。
  2. Object Visitor 提供了基于泛型,在一些特定的场景可以完全避免装箱拆箱所带来的开销。

你可以通过点击这里来查看使用反射和使用 object visitor 的基准测试

本篇小结

到这里,你已经初步了解了什么是 Newbe.ObjectVisitor,以及其基本的用法。

不过,这只是演示代码,展现的内容非常有限,因此,你还可以继续阅读下篇来进一步了解更多紧张刺激的特性。

发布说明

使用样例

开发文档可能随版本发生变化,查看最新的开发文档需移步 http://cn.ov.newbe.pro

番外分享

GitHub 项目地址:https://github.com/newbe36524/Newbe.ObjectVisitor

Gitee 项目地址:https://gitee.com/yks/Newbe.ObjectVisitor

相关文章
 
------ 本文结束 ------

0x01 - 我的第一个 Object Visitor的更多相关文章

  1. 在Salesforce中对某一个Object添加自定义的Button和Link

    在Salesforce中可以对某一个Object添加自定义的Button和Link,来完成特定的逻辑过程,接下来以一个简单的实例来描述整个处理流程,实现的基本功能和我另外一篇文章中描述的功能是一致的( ...

  2. 在Salesforce中可以对某一个Object的Standard Button或Link进行重写

    在Salesforce中可以对某一个Object的Standard Button或Link进行重写,来实现我们特定的逻辑过程,比如:在删除某个Object之前要判断该Object的某个Field的状态 ...

  3. 在Salesforce中对某一个Object添加 Validation Rule

    在Salesforce中可以对某一个Object添加相应的 Validation Rule 来进行一个全局的条件判断,比如满足什么样的条件的修改允许提交,不满足的要提示相应的错误信息. 要创建一个Va ...

  4. new一个Object对象占用多少内存?

    Java的自动内存管理机制省却了很多编码工作,大大地提高了Java的生产力,而且JVM的性能也越来越好,特别是G1的出现,改善了垃圾回收中stop the world的状况. 也许很多人都没有考虑过这 ...

  5. [转]new一个Object对象占用多少内存?

    我们分解下ArrayList arr = new ArrayList();等同于ArrayList arr = null;//初始化arr = new ArrayList();//实例化这两个过程.初 ...

  6. list,set等集合遍历时,不能remove集合中的元素。需要new一个Object或者list,set,里面add需要删除的元素,等集合遍历完了进行remove(Object)或者removeAll(list/set)操作

    list,set等集合遍历时,不能remove集合中的元素.需要new一个Object或者list,set,里面add需要删除的元素,等集合遍历完了进行remove(Object)或者removeAl ...

  7. php 分享一个object(stdclass)转数组的函数

    经常调用一个借口之后 返回的内容是json串,利用php函数json_decode() 解析json串之后得到的 数据类型为object(stdclass) 这是一个对象,要取其中的内容也可以 取得, ...

  8. 小程序的picker的range 是一个 Object Array (对象数组)

    小程序的picker的range 是一个 Object Array (对象数组) 数据: array: [{'id':1,'name':'Android'},{'id':2,'name':'IOS'} ...

  9. django保存一个object的时候会发出信号

    当django保存一个object的时候会发出一系列的signals,可以通过对这些signals注册listener,从而相应的signal发出时执行一定的代码. from django.core. ...

  10. 好用的一个object c 宏

    好用的一个object c 宏 from https://github.com/justzt/ios-helper/blob/master/Macro.h // // Macro.h // Photo ...

随机推荐

  1. Ollama模型迁移

    技术背景 在前面的一些文章中,我们介绍过使用Ollama在Linux平台加载DeepSeek蒸馏模型,使用Ollama在Windows平台部署DeepSeek本地模型.除了使用Ollama与模型文件交 ...

  2. MySQL - [16] SSL

    MySQL8的SSL功能可以帮助用户更安全地管理数据库,提高数据安全性. 一.SSL概念 SSL(Secure Socket Layer:安全套接字)利用数据加密,身份验证和消息完整性验证机制,为基于 ...

  3. 网线 - 568B接法

  4. LCP 06. 拿硬币

    地址:https://leetcode-cn.com/problems/na-ying-bi/ <?php /** * Class Solution * 桌上有 n 堆力扣币,每堆的数量保存在数 ...

  5. 【Python脚本】刚度矩阵格式转换

    对于1-2-3坐标系: 应力矩阵如下: \[\left.[\sigma]=\left[\begin{array}{ccc}\sigma_{11}&\sigma_{12}&\sigma_ ...

  6. 强!10.8K star!推荐一款用于威胁预防、安全检测的开源监控平台,功能非常强大!!

    在当今数字化时代,网络安全威胁日益严峻,企业和组织对于高效.强大的安全解决方案的需求也愈发迫切. 今天给大家分享一个专注于安全监控的开源项目:Wazuh,正是应对这一挑战的有力武器,专门用于帮助个人和 ...

  7. MS17_010漏洞利用,渗透win7,拿到桌面的flag

    关于使用MS17_010来攻击WIN7: 我们先ping一下win7的ip看看是否可以ping通(ping不通的可以关闭win7的防火墙),然后我们用nmap扫一下看看靶机有什么漏洞 nmap --s ...

  8. Anaconda使用记录

    1 安装 windows下,安装完添加环境变量(哦安装时勾选添加环境变量选项就是加这些变量的) ## (记anaconda软件目录为%ANACONDA3%) %ANACONDA3%\ %ANACOND ...

  9. js里一些实在想不通的问题合集

    The global NaN property is a value representing Not-A-Number. --MDN NaN 是用来表示一个非数字的值得全局属性, 但是typeof之 ...

  10. 数据、信息、知识、智慧:AI时代我们该如何思考?

    时代的浪潮滚滚向前,AI技术的演进正悄然改变着我们认知世界和创造价值的方式.从数据.信息到知识.智慧,从大数据到大模型,从单一智能体到多智能体协作,这是一场深刻的认知革命,也是生产力解放的新纪元. A ...