只要十步,你就可以应用表达式树来优化动态调用(一)( 二 )
以上测试中 , 我们对第三种调用方式一百万次调用 , 并记录每个测试所花费的时间 。 可以得到类似以下的结果:
MethodTimeRunReflection 217ms
RunExpression 20ms
Directly 19ms
可以得出以下结论:
- 使用表达式树创建委托进行动态调用可以得到和直接调用近乎相同的性能 。
- 使用表达式树创建委托进行动态调用所消耗的时间约为十分之一 。
不过这是在一百万调用下体现出现的时间 , 对于单次调用而言其实就是纳秒级别的区别 , 其实无足轻重 。
但其实表达式树不仅仅在性能上相较于反射更优 , 其更强大的扩展性其实采用最为重要的特性 。
此处还有一个对属性进行操作的测试 , 此处将测试代码和结果罗列如下:
using System;using System.Diagnostics;using System.Linq.Expressions;using System.Reflection;using FluentAssertions;using NUnit.Framework;namespace Newbe.ExpressionsTests{public class X02PropertyTest{private const int Count = 1_000_000;private const int Diff = 100;[SetUp]public void Init(){_propertyInfo = typeof(Claptrap).GetProperty(nameof(Claptrap.Level));Debug.Assert(_propertyInfo != null, nameof(_propertyInfo) + " != null");var instance = Expression.Parameter(typeof(Claptrap), "c");var levelProperty = Expression.Property(instance, _propertyInfo);var levelP = Expression.Parameter(typeof(int), "l");var addAssignExpression = Expression.AddAssign(levelProperty, levelP);var lambdaExpression = Expression.Lambda>(addAssignExpression, instance, levelP);// lambdaExpression should be as (Claptrap c,int l) =>{ c.Level += l; }_func = lambdaExpression.Compile();}[Test]public void RunReflection(){var claptrap = new Claptrap();for (int i = 0; i < Count; i++){var value = http://kandian.youth.cn/index/(int) _propertyInfo.GetValue(claptrap);_propertyInfo.SetValue(claptrap, value + Diff);}claptrap.Level.Should().Be(Count * Diff);}[Test]public void RunExpression(){var claptrap = new Claptrap();for (int i = 0; i < Count; i++){_func.Invoke(claptrap, Diff);}claptrap.Level.Should().Be(Count * Diff);}[Test]public void Directly(){var claptrap = new Claptrap();for (int i = 0; i < Count; i++){claptrap.Level += Diff;}claptrap.Level.Should().Be(Count * Diff);}private PropertyInfo _propertyInfo;private Action _func;public class Claptrap{public int Level { get; set; }}}}
耗时情况:MethodTimeRunReflection 373ms
RunExpression 19ms
Directly 18ms
由于反射多了一份装拆箱的消耗 , 所以比起前一个测试样例显得更慢了 , 使用委托是没有这种消耗的 。
第〇步 , 需求演示先通过一个测试来了解我们要创建的 “模型验证器” 究竟是一个什么样的需求 。
using System.ComponentModel.DataAnnotations;using FluentAssertions;using NUnit.Framework;namespace Newbe.ExpressionsTests{////// Validate data by static method///public class X03PropertyValidationTest00{private const int Count = 10_000;[Test]public void Run(){for (int i = 0; i < Count; i++){// test 1{var input = new CreateClaptrapInput();var (isOk, errorMessage) = Validate(input);isOk.Should().BeFalse();errorMessage.Should().Be("missing Name");}// test 2{var input = new CreateClaptrapInput{Name = "1"};var (isOk, errorMessage) = Validate(input);isOk.Should().BeFalse();errorMessage.Should().Be("Length of Name should be great than 3");}// test 3{var input = new CreateClaptrapInput{Name = "yueluo is the only one dalao"};var (isOk, errorMessage) = Validate(input);isOk.Should().BeTrue();errorMessage.Should().BeNullOrEmpty();}}}public static ValidateResult Validate(CreateClaptrapInput input){return ValidateCore(input, 3);}public static ValidateResult ValidateCore(CreateClaptrapInput input, int minLength){if (string.IsNullOrEmpty(input.Name)){return ValidateResult.Error("missing Name");}if (input.Name.Length
- 只需799元就可以把旧iPad换成新款iPad?是真的!但这羊毛可没那么容易薅
- 马化腾这招太高明!网友:只要我改名的速度够快,禁令就追不上我
- 飞腾桌面腾锐D2000 CPU发布:最高2.6GHz、八核只要25W
- 苹果官网产品出现 Bug 价:上千元产品显示只要一两百元
- 华为手机为什么耗电快?只要关闭手机这6个开关,2天1充不是梦
- 苏宁易购双十二10亿补贴引爆吃货狂欢,西贝明星单品只要9.9
- 别错过,双节钜惠还有2天结束
- 人群|出差旅行也能带呼吸机?M1 Mini就可以
- 瑞士宽带商TWiFi可提供18年免费上网服务
- 5G新选择:支持65W快充,8G+128G只要1599元