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

基于,sqlsugar,开发,框架,循序渐进,介绍,使用,serialize,linq,lambda,表达式,进行,序列化 · 浏览次数 : 995

小编点评

**基于SqlSugar的开发框架循序渐进介绍** **1.概述** * SQLSugar开发框架介绍 *系列文章:《基于SqlSugar的开发框架的循序渐进介绍(1)--框架基础类的设计和使用》 **2.基础类设计** *接口注入 *用户身份信息接口 *日志记录 **3.数据库操作** *数据访问基类 *基于GUID主键自动赋值 *在数据访问基类中对GUID主键进行自动赋值处理 **4.接口注入** *在服务层使用接口注入方式实现IOC控制反转 **5.用户身份信息接口** *在基础类接口中注入用户身份信息接口 **6.代码生成工具** *数据库2Sharp **7.前端界面** *Vue3+TypeScript **8.缓存** *CSRedis **9.移动前端** *UniApp+Vue **10.多条件查询** *Vue3+TypeScript **11.表单编辑** *Vue3+TypeScript **12.表单详情查看** *Vue3+TypeScript **13.页面加载** *Vue3+TypeScript **14.序列化和反序列化** *Serialize.Linq **15.vue3+typescript的前端工作流模块** *统一的表单编辑和表单详情查看处理 **16.Winform端管理系统** *平滑增加对Web API对接的需求 **17.数据库操作** *数据访问基类 *基于GUID主键自动赋值 *在数据访问基类中对GUID主键进行自动赋值处理 **18.基于GUID主键自动赋值** *在数据访问基类中对GUID主键进行自动赋值处理 **19.数据库2Sharp** *数据库2Sharp **20.vue3+typescript的前端工作流模块** *统一的表单编辑和表单详情查看处理 **21.多条件查询** *Vue3+TypeScript **22.缓存** *CSRedis **23.移动前端** *UniApp+Vue **24.序列化和反序列化** *Serialize.Linq

正文

在上篇随笔《基于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表达式接口参数的方式了。

我们可以把其中相关的Lambda表达式,放在一个区块中,方便查看和处理,如下代码所示是在服务端的Web API控制器的基类函数处理代码。

SqlSugar开发框架介绍:https://www.iqidi.com/Framework/sugarIndex.htm 

 

系列文章:

基于SqlSugar的开发框架的循序渐进介绍(1)--框架基础类的设计和使用

基于SqlSugar的开发框架循序渐进介绍(2)-- 基于中间表的查询处理

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

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

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

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

基于SqlSugar的开发框架循序渐进介绍(7)-- 在文件上传模块中采用选项模式【Options】处理常规上传和FTP文件上传

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

基于SqlSugar的开发框架循序渐进介绍(9)-- 结合Winform控件实现字段的权限控制

基于SqlSugar的开发框架循序渐进介绍(10)-- 利用axios组件的封装,实现对后端API数据的访问和基类的统一封装处理

基于SqlSugar的开发框架循序渐进介绍(11)-- 使用TypeScript和Vue3的Setup语法糖编写页面和组件的总结

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

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

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

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

基于SqlSugar的开发框架循序渐进介绍(16)-- 工作流模块的功能介绍

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

 《基于SqlSugar的开发框架循序渐进介绍(18)-- 基于代码生成工具Database2Sharp,快速生成Vue3+TypeScript的前端界面和Winform端界面

基于SqlSugar的开发框架循序渐进介绍(19)-- 基于UniApp+Vue的移动前端的功能介绍

基于SqlSugar的开发框架循序渐进介绍(20)-- 在基于UniApp+Vue的移动端实现多条件查询的处理

基于SqlSugar的开发框架循序渐进介绍(21)-- 在工作流列表页面中增加一些转义信息的输出,在后端进行内容转换

 《基于SqlSugar的开发框架循序渐进介绍(22)-- Vue3+TypeScript的前端工作流模块中实现统一的表单编辑和表单详情查看处理 

基于SqlSugar的开发框架循序渐进介绍(23)-- Winform端管理系统中平滑增加对Web API对接的需求

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

 

与基于SqlSugar的开发框架循序渐进介绍(24)-- 使用Serialize.Linq对Lambda表达式进行序列化和反序列化相似的内容:

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

在上篇随笔《基于SqlSugar的开发框架循序渐进介绍(23)-- Winform端管理系统中平滑增加对Web API对接的需求》中介绍了基于一个接口,实现对两种不同接入方式(直接访问数据库实现,基于Web API代理类实现)的处理,由于定义的接口中,我们为了方便,也是用了Lambda表达式的进行一些参数的处理,那么如果在Web API代理类中,Lambda表达式是不能直接传递给Web API的控

基于SqlSugar的开发框架循序渐进介绍(16)-- 工作流模块的功能介绍

工作流是集成系统的模块应用,使用权限管理系统的身份认证登录后即可使用。本篇随笔介绍工作流模块的界面功能效果。

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

在一个应用系统的开发框架中,往往很多地方需要用到缓存的处理,有些地方是为了便于记录用户的数据,有些地方是为了提高系统的响应速度,如有时候我们在发送一个短信验证码的时候,可以在缓存中设置几分钟的过期时间,这样验证短信验证码的时候,就会自动判断是否过期了。本篇随笔结合CSRedis的使用,介绍如何实现缓存的初始化及使用的处理。

基于SqlSugar的开发框架循序渐进介绍(18)-- 基于代码生成工具Database2Sharp,快速生成Vue3+TypeScript的前端界面和Winform端界面

我们开发一个系统,在保证风格统一、代码强壮、可读性强等基础上,还能够结合代码生成工具快速开发相关后端,以及各种前端界面的,无疑是非常好的,既保证了项目的代码质量,又能够极大的提高开发效率。代码生成工具Database2Sharp是在完善的开发项目上,抽取出数据变化的部分,通过演绎、归纳、反复演绎和归纳等提炼方式抽取出相关的规则,以工具的方式来快速提高生产率,使得我们在开发各种不同的项目上的时候,能

基于SqlSugar的开发框架循序渐进介绍(19)-- 基于UniApp+Vue的移动前端的功能介绍

在之前的SqlSugar系列随笔中,介绍了很多我们关于SqlSugar的开发框架的内容,SqlSugar的开发框架的目的是多前端应用场景,因此其中会包含各种不同的前端应用,前面介绍了基于DevExpress的Winform的前端应用,以及基于Vue3+TypeScript+ElementPlus的BS前端应用,本篇随笔继续介绍SqlSugar的开发框架的另一个前端应用,基于UniApp+Vue+T

基于SqlSugar的开发框架循序渐进介绍(20)-- 在基于UniApp+Vue的移动端实现多条件查询的处理

在做一些常规应用的时候,我们往往需要确定条件的内容,以便在后台进行区分的进行精确查询,在移动端,由于受限于屏幕界面的情况,一般会对多个指定的条件进行模糊的搜索,而这个搜索的处理,也是和前者强类型的条件查询处理类似的处理过程,因此本篇随笔探讨两种不同查询在前端界面上的展示效果,以及后端基于.netCore的Web API端的基类进行的统一封装处理。

基于SqlSugar的开发框架循序渐进介绍(21)-- 在工作流列表页面中增加一些转义信息的输出,在后端进行内容转换

有时候,为了给前端页面输出内容,有时候我们需要准备和数据库不一样的实体信息,因为数据库可能记录的是一些引用的ID或者特殊字符,那么我们为了避免前端单独的进行转义处理,我们可以在后端进行统一的格式化后再行输出,后端处理可以采用不同的DTO尸体信息,后端对不同的实体进行映射处理即可,也可以采用同一个实体,在SqlSugar实体信息中忽略对应的字段写入实现,本篇随笔介绍后者的处理方式,实现在在工作流列表

基于SqlSugar的开发框架循序渐进介绍(22)-- Vue3+TypeScript的前端工作流模块中实现统一的表单编辑和表单详情查看处理

在工作流页面中,除了特定的业务表单信息外,往往也需要同时展示通用申请单的相关信息,因此在页面设计的时候需要使用一些组件化的概念来实现动态的内容展示处理,本篇随笔介绍Vue3+TypeScript+ElementPus的前端工作流模块中实现统一的表单编辑和表单详情查看处理。

基于SqlSugar的开发框架循序渐进介绍(23)-- Winform端管理系统中平滑增加对Web API对接的需求

在前面随笔介绍的基于SqlSugar的WInform端管理系统中,数据提供者是直接访问数据库的方式,不过窗体界面调用数据接口获取数据的时候,我们传递的是标准的接口,因此可扩展性比较好。我曾经在随笔《基于SqlSugar的开发框架循序渐进介绍(5)-- 在服务层使用接口注入方式实现IOC控制反转》中介绍过,该SqlSugar开发框架本身是基于IOC控制反转的,因此对于接入不同的数据提供者,只需要切换

基于SqlSugar的开发框架循序渐进介绍(25)-- 基于SignalR实现多端的消息通讯

基于ASP.NET Core SignalR 可以实现客户端和服务器之间进行即时通信。本篇随笔介绍一些SignalR的基础知识,以及结合对SqlSugar的开发框架的支持,实现SignalR的多端处理整合,从而实现Winform客户端,基于Vue3+ElementPlus的BS端整合,后面也可以实现对移动端的SignalR的整合通讯。