只要十步,你就可以应用表达式树来优化动态调用(一)( 三 )

< minLength){return ValidateResult.Error($"Length of Name should be great than {minLength}");}return ValidateResult.Ok();}public class CreateClaptrapInput{[Required] [MinLength(3)] public string Name { get; set; }}public struct ValidateResult{public bool IsOk { get; set; }public string ErrorMessage { get; set; }public void Deconstruct(out bool isOk, out string errorMessage){isOk = IsOk;errorMessage = ErrorMessage;}public static ValidateResult Ok(){return new ValidateResult{IsOk = true};}public static ValidateResult Error(string errorMessage){return new ValidateResult{IsOk = false,ErrorMessage = errorMessage};}}}}从上而下 , 以上代码的要点:

  1. 主测试方法中 , 包含有三个基本的测试用例 , 并且每个都将执行一万次 。 后续所有的步骤都将会使用这样的测试用例 。
  2. Validate 方法是被测试的包装方法 , 后续将会调用该方法的实现以验证效果 。
  3. ValidateCore 是 “模型验证器” 的一个演示实现 。 从代码中可以看出该方法对 CreateClaptrapInput 对象进行的验证 , 并且得到验证结果 。 但是该方法的缺点也非常明显 , 这是一种典型的 “写死” 。 后续我们将通过一系列改造 。 使得我们的 “模型验证器” 更加的通用 , 并且 , 很重要的 , 保持和这个 “写死” 的方法一样的高效!
  4. ValidateResult 是验证器输出的结果 。 后续将不断重复的用到该结果 。
第一步 , 调用静态方法首先我们构建第一个表达式树 , 该表达式树将直接使用上一节中的静态方法 ValidateCore 。
using System;using System.ComponentModel.DataAnnotations;using System.Diagnostics;using System.Linq.Expressions;using FluentAssertions;using NUnit.Framework;namespace Newbe.ExpressionsTests{////// Validate date by func created with Expression///public class X03PropertyValidationTest01{private const int Count = 10_000;private static Func _func;[SetUp]public void Init(){try{var method = typeof(X03PropertyValidationTest01).GetMethod(nameof(ValidateCore));Debug.Assert(method != null, nameof(method) + " != null");var pExp = Expression.Parameter(typeof(CreateClaptrapInput));var minLengthPExp = Expression.Parameter(typeof(int));var body = Expression.Call(method, pExp, minLengthPExp);var expression = Expression.Lambda>(body,pExp,minLengthPExp);_func = expression.Compile();}catch (Exception e){Console.WriteLine(e);throw;}}[Test]public void Run(){// see code in demo repo}public static ValidateResult Validate(CreateClaptrapInput input){return _func.Invoke(input, 3);}public static ValidateResult ValidateCore(CreateClaptrapInput input, int minLength){if (string.IsNullOrEmpty(input.Name)){return ValidateResult.Error("missing Name");}if (input.Name.Length < minLength){return ValidateResult.Error($"Length of Name should be great than {minLength}");}return ValidateResult.Ok();}}}从上而下 , 以上代码的要点:
  1. 增加了一个单元测试的初始化方法 , 在单元测试启动时创建的一个表达式树将其编译为委托保存在静态字段 _func 中 。
  2. 省略了主测试方法 Run 中的代码 , 以便读者阅读时减少篇幅 。 实际代码没有变化 , 后续将不再重复说明 。 可以在代码演示仓库中查看 。


    推荐阅读