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

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

时间:2022-12-26 16:55:08浏览次数:72  
标签:24 -- express API 序列化 Expression 表达式 Lambda

在上篇随笔《基于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控制器的基类函数处理代码。

 

标签:24,--,express,API,序列化,Expression,表达式,Lambda
From: https://www.cnblogs.com/wuhuacong/p/17006100.html

相关文章

  • 简单认识APP项目
     manifests:里面只有一个xml,是app运行配置文件清单文件<?xmlversion="1.0"encoding="utf-8"?><manifestxmlns:android="http://schemas.android.com/apk/res/andr......
  • python 自动点击微信 文件传输助手链接
    fromwxautoimportWeChatimportpywinauto,time,sys,re,random#获取当前微信客户端wx=WeChat()#获取会话列表wx.GetSessionList()#输出当前聊天窗口聊天......
  • Task.Run vs Task.Factory.StartNew
    Task.Factory.StartNew内部开启子线程后的调度等待慢的问题。将同步阻塞改为不依赖环境上下文的方式:async/awaitInterestingly,thenewawaitkeywordcanalmostbe......
  • 构造方法
    类和对象的区别?我们可以把类理解成对于一个物品的设计图纸,对象就是那个具体的物品.也即类的实例化.比如下面的这个类publicclassPerson{publicintage;......
  • lightweight openpose比coco数据集的keypoint多俩个通道
    第一个通道是neck是虚拟点用左肩膀和右肩膀的均值作为neck坐标,第二个通道是背景图即1-所有背景图的最大像素。coco数据集只有17个关键点。生成neck在transformer里。生......
  • D365: Graph API(三)程序调用Graph API
    D365:GraphAPI(三)程序调用GraphAPI在D365中,系统通过GraphAPIClient封装了GraphAPI接口,可以直接通过调用SysUserMSODSImportHelper::getGraphAPIClient().ListUsers()......
  • 局域网大文件上传详解及实例代码
    ​ 最近遇见一个需要上传百兆大文件的需求,调研了七牛和腾讯云的切片分段上传功能,因此在此整理前端大文件上传相关功能的实现。在某些业务中,大文件上传是一个比较重要的......
  • C# byte[]数据流/base64数据流转pdf文件
    pdf转byte[]再转pdf文件进行保存///<summary>///pdf转byte[]再转pdf文件进行保存///</summary>///<paramname="sender"></param......
  • EtherCAT
    EtherCAT源码https://github.com/OpenEtherCATsociety/SOEM在github上获取.zip格式源码并解压,目前master分支上默认是最新的1.4.0版本。进入根目录,README.md有编译步骤......
  • mysql自动增长设置
    首先将那个要增长的键设成主键,然后再进行设置初始值和增长步长。例如:现在一张book表1altertablebookaddidBIGINT;--为book表增加一个名称为id,类型为bigint的列......