在上篇随笔《基于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. jq判断页面滚动条进行样式修改

    $(window).scroll(function(){//窗口的滚动条 if($(window).scrollTop()>100){ //垂直滚动条钓offset 大于90时. $(" ...

  2. ES6中的数组reduce()方法详解

    reduce() 方法对数组中的每个元素执行一个由我们提供的reducer函数(升序执行),将其结果汇总为单个返回值. 1. 语法reduce说明 arr.reduce(callback(accumu ...

  3. 关于windows-server-下MySQL Community版本的的安装与配置

    在公司电脑或者服务器上安装软件,都是有要求的,要么购买license-(这个需要申请,难度较大),要么安装免费开源的软件 笔者最近想要安装mysql服务环境,用于数据存储及开发一些功能程序需要连接数据 ...

  4. 不安装运行时运行 .NET 程序 - NativeAOT

    大家好,先祝大家国庆快乐.不过大家看到这篇文章的时候估计已经过完国庆了 . 上一篇我们写了如何通过 SelfContained 模式发布程序(不安装运行时运行.NET程序)达到不需要在目标机器上安装 ...

  5. 细聊.Net Core中IServiceScope的工作方式

    前言 自从.Net Core引入IOC相关的体系之后,关于它的讨论就从来没有停止过,因为它是.Net Core体系的底层框架,你只要使用了.Net Core的时候就必然会用到它.当然关于使用它的过程中 ...

  6. 3.MongoDB系列之查询

    1. find简介 // 查询所有文档 db.users.find({}) // 查询指定条件文档 db.users.find({'name': 'shenjian'}) // 查询指定字段,1查询键 ...

  7. Response对象页面重定向、时间的动态显示

    Response对象 response对象主要用于对客户端的请求进行回应,将web服务器处理后的结果发回给客户端,封装了jsp产生的响应,并发送到客户端响应客户端的请求,请求的数据可以是各种数据类型, ...

  8. 一天五道Java面试题----第九天(简述MySQL中索引类型对数据库的性能的影响--------->缓存雪崩、缓存穿透、缓存击穿)

    这里是参考B站上的大佬做的面试题笔记.大家也可以去看视频讲解!!! 文章目录 1.简述MySQL中索引类型对数据库的性能的影响 2.RDB和AOF机制 3.Redis的过期键的删除策略 4.Redis ...

  9. 齐博x1标签之异步加载标签数据

    为什么要异步加载标签?他有什么好处 如果一个页面的标签太多,又或者是页面中某一个标签调用数据太慢的话,就会拖慢整个页面的打开,非常影响用户体验.这个时候,用异步加载的话,就可以一块一块的显示,用户体验 ...

  10. ysoserial commonscollections3 分析

    cc3利用链如下: TrAXFilter(Templates templates) TemplatesImpl->newTransformer() TemplatesImpl->getTr ...