在上篇随笔《基于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. GitHub 供应链安全已支持 Dart 开发者生态

    通过 Dart 和 GitHub 团队的共同努力,自 10 月 7 日起,GitHub 的 Advisory Database (安全咨询数据库).Dependency Graph (依赖项关系图) ...

  2. Flink的异步算子的原理及使用

    1.简介 Flink的特点是高吞吐低延迟.但是Flink中的某环节的数据处理逻辑需要和外部系统交互,调用耗时不可控会显著降低集群性能.这时候就可能需要使用异步算子让耗时操作不需要等待结果返回就可以继续 ...

  3. Java多线程(4):ThreadLocal

    您好,我是湘王,这是我的博客园,欢迎您来,欢迎您再来- 为了提高CPU的利用率,工程师们创造了多线程.但是线程们说:要有光!(为了减少线程创建(T1启动)和销毁(T3切换)的时间),于是工程师们又接着 ...

  4. 前端JS模板引擎Mustache.js的用法

    Mustache.js在前端是一个非常强大的模板 Mustache用法参考

  5. SIP会话发起协议 - 先知道是什么(一)

    少年,思无邪,最最动人. 协议概述 SIP会话发起协议是VoIP技术中最常用的协议之一.它是一种应用层协议,与其它应用层协议协同工作,通过Internet控制多媒体通信会话. SIP采用SDP(会话描 ...

  6. 检测轮廓 获取其最值的坐标 opencv-python

    一.基础知识 图像清晰度评价算法有多种 空域中,主要考察图像的邻域对比度,即相邻像素间灰度特征的 梯度差: 频域中,主要考察图像的频率分量,清晰的图像高频分量多,模糊的图像低频分量多. 灰度值 把白色 ...

  7. vue 项目中不更新的问题

    在项目中 做矩阵题  嵌套的v-for <!-- 多选矩阵题 --> <template v-if="question.name==='MATRIX_CHECKBOX'&q ...

  8. vue 数组更新(push【可用】,$set,slice,filter,map【都属于浅拷贝】)问题

    this.$axios.post('https://....php',this.$qs.stringify({ user: 'suess' })) .then(res => { this.dat ...

  9. Perl读取Excel中的数据

    #!usr/bin/perl -W use strict; use Spreadsheet::ParseExcel;#PERL的Spreadsheet::ParseExcel模块支持Excel的读操作 ...

  10. 【OpenStack云平台】安装Centos操作系统

    视频教程:https://live.csdn.net/v/236820 1.环境准备 准备实验所需要的环境,需要安装VMware Workstation.使用的系统镜像为CentOS-7.5-x86_ ...