在上篇随笔《基于SqlSugar的开发框架循序渐进介绍(23)-- Winform端管理系统中平滑增加对Web API对接的需求》中介绍了基于一个接口,实现对两种不同接入方式(直接访问数据库实现,基于Web API代理类实现)的处理,由于定义的接口中,我们为了方便,也是用了Lambda表达式的进行一些参数的处理,那么如果在Web API代理类中,Lambda表达式是不能直接传递给Web API的控制器的,那么如何对这个Lambda表达式进行序列化和反序列化还原就是一个急需解决的问题。 本篇随笔介绍采用Serialize.Linq 第三方组件的方式实现对Lambda表达式进行序列化和反序列化的处理。

1、Lambda表达式的接口使用

Lambda 表达式本质上是一个匿名函数,是C#中一种特殊语法,它的引入,使得匿名方法更加简单易用,最直接的是在方法体内调用代码或者为委托传入方法体的形式与过程变得更加优雅。 使用Lambda表达式可大大减少代码量,使得代码更加的优美、简洁,更有可观性。由于Lambda表达式的便利性,因此虽然在整合多个接入实现比较麻烦一些,我依旧希望通过寻找方法实现对Lambda表达式的兼容处理。

例如,以下就是一个根据名称简单进行判断的Lambda表达式的处理。

/// <summary>
/// 新增状态下的数据保存
/// </summary>
/// <returns></returns>
public async override Task<bool> SaveAddNew()
{
CustomerInfo info = tempInfo;//必须使用存在的局部变量,因为部分信息可能被附件使用
SetInfo(info);
try
{
#region 新增数据
//检查是否还有其他相同关键字的记录
bool isExist = await BLLFactory<ICustomerService>.Instance.IsExistAsync(s=> s.Name.Equals(info.Name));
if (isExist)
{
MessageDxUtil.ShowTips("指定的【姓名】已经存在,不能重复添加,请修改");
return false;
} var success = await BLLFactory<ICustomerService>.Instance.InsertAsync(info);
if (success)
{
//可添加其他关联操作
return true;
}
#endregion
}
catch (Exception ex)
{
LogTextHelper.Error(ex);
MessageDxUtil.ShowError(ex.Message);
}
return false;
}

它的函数原型就是一个Lambda表达式,如下所示的定义

/// <summary>
/// 判断是否存在指定条件的记录
/// </summary>
/// <param name="input">表达式条件</param>
/// <returns></returns>
Task<bool> IsExistAsync(Expression<Func<TEntity, bool>> input);

有些稍微复杂一点的函数,如下定义所示。

/// <summary>
/// 获取某字段数据字典列表
/// </summary>
Task<List<string>> GetFieldList(Expression<Func<TEntity, object>> selector, Expression<Func<TEntity, bool>> where = null);

调用的时候,如下所示。

/// <summary>
/// 初始化数据字典
/// </summary>
private async void InitDictItem()
{
//初始化代码
var list = await BLLFactory<IFormService>.Instance.GetFieldList(s=> s.Category);
this.txtCategory.BindDictItems(list, "");
}

不过简单是简单了,但是本身Lambda表达式不能直接传递给Web API端参数,因为它无法直接序列化进行传递。

我们在之前说过,接入两种不同的数据提供方式。

因此我们为了继续使用Lambda表达是的优点,就需要使用Serialize.Linq对Lambda表达式进行序列化和反序列化。这样就可以在Web API端和Web API 代理端对Lambda表达式进行正常的使用了。

2、采用Serialize.Linq 对Lambda表达式进行序列化和反序列化的处理

首先在需要的地方,引入Serialize.Linq对Lambda表达式进行序列化和反序列化处理。

为了更好通用的实现Lambda表达式的正常序列化为文本,以及对文本的反序列化到Lambda表达式,我们这里编写了一个扩展函数,以便更方便的处理。

    /// <summary>
/// 对Lambda表达式的序列号和反序列化处理
/// </summary>
public static class SerializeExtension
{
/// <summary>
/// 序列化 LINQ Expression 表达式为JSON文本
/// </summary>
/// <typeparam name="TEntity">处理对象类型</typeparam>
/// <typeparam name="TResult">返回结果类型</typeparam>
/// <param name="express"></param>
/// <returns></returns>
public static string SerializeText<TEntity, TResult>(this Expression<Func<TEntity, TResult>> express)
{
//使用Serialize.Linq组件序列化表达式,传递给API端,API端需要对应反序列化的处理操作进行转换Expression
var serializer = new ExpressionSerializer(new JsonSerializer());
var expressJson = serializer.SerializeText(express); //接收端的反序列化处理
//var express = (Expression<Func<TEntity, TResult>>)serializer.DeserializeText(expressJson); return expressJson;
} /// <summary>
/// 反序列化JSON文本为LINQ Expression 表达式
/// </summary>
/// <typeparam name="TEntity">处理对象类型</typeparam>
/// <typeparam name="TResult">返回结果类型</typeparam>
/// <param name="text"></param>
/// <returns></returns>
public static Expression<Func<TEntity, TResult>> DeserializeText<TEntity, TResult>(this string json)
{
Expression<Func<TEntity, TResult>> express = null;
if (!string.IsNullOrWhiteSpace(json))
{
var serializer = new ExpressionSerializer(new JsonSerializer());
express = (Expression<Func<TEntity, TResult>>)serializer.DeserializeText(json);
}
return express;
}
}

这样我们来看看两个对Lambda表达式的Web API代理类的封装处理代码

        /// <summary>
/// 根据条件,获取所有记录
/// </summary>
public virtual async Task<ListResultDto<TEntity>> GetAllAsync(Expression<Func<TEntity, bool>> input, string orderBy = null)
{
var express = input.SerializeText(); //使用扩展函数处理生成JSON
var postData = new
{
express,
orderBy
};
return await DoActionAsync<ListResultDto<TEntity>>("all-expression", postData, HttpVerb.Post);
} /// <summary>
/// 根据条件计算记录数量
/// </summary>
/// <returns></returns>
public virtual async Task<long> CountAsync(Expression<Func<TEntity, bool>> input)
{
var expressJson = input.SerializeText(); //使用扩展函数处理生成JSON
return await DoActionAsync<long>("count-expression", expressJson, HttpVerb.Post);
}

而对应的在Web API的基类控制器中,我们对这个通用的实现处理下就可以了

        /// <summary>
/// 根据条件,获取所有记录
/// </summary>
[HttpPost]
[Route("all-expression")]
public async Task<ListResultDto<TEntity>> GetAllAsync(ExpressionOrderDto input)
{
ListResultDto<TEntity>? result = null; string json = input.expression;
var express = json.DeserializeText<TEntity, bool>(); if (express != null)
{
result = await _service.GetAllAsync(express!);
} return result;
} [HttpPost]
[Route("count-expression")]
public virtual async Task<long> CountAsync(dynamic expressJson)
{
long result = 0;
string json = expressJson;
var express = json.DeserializeText<TEntity, bool>(); if (express != null)
{
result = await _service.CountAsync(express!);
}
return result;
}

这样在服务器端的Web API控制器上,就还原了原先的Lambda表达式,可以正常的接收到客户端提交的条件处理了。

通过这样的迂回的方式,我们就可以在常规的接口,以及Web  API的代理类中,都可以使用到Lambda表达式带来的便利性了,而不需要为了兼容而抛弃Lambda表达式接口参数的方式了。

基于SqlSugar的开发框架循序渐进介绍(24)-- 使用Serialize.Linq对Lambda表达式进行序列化和反序列化的更多相关文章

  1. 基于SqlSugar的开发框架循序渐进介绍(6)-- 在基类接口中注入用户身份信息接口

    在基于SqlSugar的开发框架中,我们设计了一些系统服务层的基类,在基类中会有很多涉及到相关的数据处理操作的,如果需要跟踪具体是那个用户进行操作的,那么就需要获得当前用户的身份信息,包括在Web A ...

  2. 基于SqlSugar的开发框架循序渐进介绍(17)-- 基于CSRedis实现缓存的处理

    在一个应用系统的开发框架中,往往很多地方需要用到缓存的处理,有些地方是为了便于记录用户的数据,有些地方是为了提高系统的响应速度,如有时候我们在发送一个短信验证码的时候,可以在缓存中设置几分钟的过期时间 ...

  3. 基于SqlSugar的开发框架循序渐进介绍(3)-- 实现代码生成工具Database2Sharp的整合开发

    我喜欢在一个项目开发模式成熟的时候,使用代码生成工具Database2Sharp来配套相关的代码生成,对于我介绍的基于SqlSugar的开发框架,从整体架构确定下来后,我就着手为它们量身定做相关的代码 ...

  4. 基于SqlSugar的开发框架循序渐进介绍(4)-- 在数据访问基类中对GUID主键进行自动赋值处理

    我们在设计数据库表的时候,往往为了方便,主键ID一般采用字符串类型或者GUID类型,这样对于数据库表记录的迁移非常方便,而且有时候可以在处理关联记录的时候,提前对应的ID值.但有时候进行数据记录插入的 ...

  5. 基于SqlSugar的开发框架循序渐进介绍(5)-- 在服务层使用接口注入方式实现IOC控制反转

    在前面随笔,我们介绍过这个基于SqlSugar的开发框架,我们区分Interface.Modal.Service三个目录来放置不同的内容,其中Modal是SqlSugar的映射实体,Interface ...

  6. 基于SqlSugar的开发框架循序渐进介绍(8)-- 在基类函数封装实现用户操作日志记录

    在我们对数据进行重要修改调整的时候,往往需要跟踪记录好用户操作日志.一般来说,如对重要表记录的插入.修改.删除都需要记录下来,由于用户操作日志会带来一定的额外消耗,因此我们通过配置的方式来决定记录那些 ...

  7. 基于SqlSugar的开发框架循序渐进介绍(12)-- 拆分页面模块内容为组件,实现分而治之的处理

    在早期的随笔就介绍过,把常规页面的内容拆分为几个不同的组件,如普通的页面,包括列表查询.详细资料查看.新增资料.编辑资料.导入资料等页面场景,这些内容相对比较独立,而有一定的代码量,本篇随笔介绍基于V ...

  8. 基于SqlSugar的开发框架循序渐进介绍(13)-- 基于ElementPlus的上传组件进行封装,便于项目使用

    在我们实际项目开发过程中,往往需要根据实际情况,对组件进行封装,以更简便的在界面代码中使用,在实际的前端应用中,适当的组件封装,可以减少很多重复的界面代码,并且能够非常简便的使用,本篇随笔介绍基于El ...

  9. 基于SqlSugar的开发框架循序渐进介绍(14)-- 基于Vue3+TypeScript的全局对象的注入和使用

    刚完成一些前端项目的开发,腾出精力来总结一些前端开发的技术点,以及继续完善基于SqlSugar的开发框架循序渐进介绍的系列文章,本篇随笔主要介绍一下基于Vue3+TypeScript的全局对象的注入和 ...

  10. 基于SqlSugar的开发框架循序渐进介绍(15)-- 整合代码生成工具进行前端界面的生成

    在前面随笔<基于SqlSugar的开发框架循序渐进介绍(12)-- 拆分页面模块内容为组件,实现分而治之的处理>中我们已经介绍过,对于相关的业务表的界面代码,我们已经尽可能把不同的业务逻辑 ...

随机推荐

  1. P7476 苦涩 题解

    Link 一道很好的复杂度均摊题目. 只需要考虑删除操作时的时间复杂度.保证复杂度的重点之一是精确定位到所有包含最大值的区间,即不去碰多余的区间.每次删除操作会删除若干个整个区间,以及至多两个区间被删 ...

  2. HDU3001 Travelling (状压DP)

    题目没有起点限制,且每个节点至少访问1次,最多访问2次,所以用三进制数表示节点的状态(选取情况). 因为三进制数的每一位是0或1或2,所以预处理z状态S的第j位的数是有必要的. 边界条件:dp[tri ...

  3. 插件化编程之WebAPI统一返回模型

    WebApi返回数据我们一般包裹在一个公共的模型下面的,而不是直接返回最终数据,在返回参数中,显示出当前请求的时间戳,是否请求成功,如果错误那么错误的消息是什么,状态码(根据业务定义的值)等等.我们常 ...

  4. day09-2视图和用户权限

    视图和用户权限 1.视图(view) 看一个需求 emp表的列信息很多,有些信息是个人重要信息(比如:sal.comm.mgr.hiredate),如果我们希望某个用户只能查询emp表的empno.e ...

  5. 算法设计(动态规划应用实验报告)实现基于贪婪技术思想的Prim算法、Dijkstra算法

    一.名称 动态规划法应用 二.目的 1.贪婪技术的基本思想: 2.学会运用贪婪技术解决实际设计应用中碰到的问题. 三.要求 1.实现基于贪婪技术思想的Prim算法: 2.实现基于贪婪技术思想的Dijk ...

  6. python同时识别多张人脸(运用face_recognition)

    之前发的博客和网上流传的代码严格来说都只算得上是人脸检测,不能区别人脸,今天来说说真的人脸识别 篇幅所限,就举两张人脸的例子了,本程序需要安装face_recognition 下面是全部源代码: im ...

  7. 24.-Django生成csv文件及下载

    一.csv文件定义 逗号分隔值(comma-separated values, csv,有时页称字符分隔值,因为分分隔字符页可以不是逗号),其文件以纯文本形式存储表格数据(数字和文本) 说明:可被常见 ...

  8. VUE v-model 语法糖

    v-model 语法糖 描述:弹出利用v-model语法糖 父组件 子组件

  9. vue-axios删除操作

    <template> <div class="nav"> <input v-model="location" type=" ...

  10. 使用WSL2连接USB设备

    目录 要求 安装 第一步 在Window安装usbipd 第二步 在WSL里安装USBIP 工具和硬件数据库 使用方法 22.3.19 微软官方文档:连接 USB 设备 | Microsoft Doc ...