在上篇随笔《基于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. POJ1741 tree (点分治模板)

    题目大意: 给一棵有 n 个顶点的树,每条边都有一个长度(小于 1001 的正整数).定义 dist(u,v)=节点 u 和 v 之间的最小距离.给定一个整数 k,对于每一对 (u,v) 顶点当且仅当 ...

  2. python锦鲤

    今日内容目录 垃圾回收机制 流程控制理论& 流程控制之分支结构& 流程控制之循环结果& 详情 Python垃圾回收机制 """ 有一些语言,内存空 ...

  3. 自主创建mybtis管理应用,用以横向管理数据源

    这个是我写的第一个随手小记,一晃眼做后端开发也有7年多了,现在也准备将一些杂七杂八的资料整理下.也算是回顾这7年中做的比较有意思的东西了. 这个需求是我17年做的,当时的应用场景是仓储库比较多,随时会 ...

  4. oracle 12C 《服务器、客户端安装》

    oracle 12C <服务器.客户端安装> 1.下载database和client database和client下载地址:http://www.oracle.com/technetwo ...

  5. 云计算_Apache CloudStack

    注:基于系统版本CentOS 7.2.1511部署 修改主机名/IP地址/hosts解析 hostnamectl set-hostname centos1 hostnamectl set-hostna ...

  6. python django超链接

    之前用django框架打了一个简易的博客网站,现在说说怎么用django做超链接. 本文基于之前讲解的博客应用,如果只想学超链接请自行删减代码或评论提问. 首先,在templates文件夹下添加det ...

  7. 基于.NetCore开发博客项目 StarBlog - (19) Markdown渲染方案探索

    前言 笔者认为,一个博客网站,最核心的是阅读体验. 在开发StarBlog的过程中,最耗时的恰恰也是文章的展示部分功能. 最开始还没研究出来如何很好的使用后端渲染,所以只能先用Editor.md组件做 ...

  8. 快速创建软件安装包-ClickOnce

    大家好,我是沙漠尽头的狼. .NET是免费,跨平台,开源,用于构建所有应用的开发人员平台. 今天介绍使用ClickOnce制作软件安装包,首先我们先了解什么是ClickOne. 1. 什么是Click ...

  9. h5 websocket 断开重新连接

    最近的项目中使用ws 长连接来接收和发送消息, 直接上代码 import * as SockJS from "sockjs-client"; import Stomp from & ...

  10. 《吐血整理》高级系列教程-吃透Fiddler抓包教程(34)-Fiddler如何抓取微信小程序的包-上篇

    1.简介 有些小伙伴或者是童鞋们说小程序抓不到包,该怎么办了???其实苹果手机如果按照宏哥前边的抓取APP包的设置方式设置好了,应该可以轻松就抓到包了.那么安卓手机小程序就比较困难,不是那么友好了.所 ...