【NetCore】调整表达式目录树实现并发布到NuGet
2021/10/18 6:10:23
本文主要是介绍【NetCore】调整表达式目录树实现并发布到NuGet,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
调整表达式目录树实现并发布到NuGet
上一篇:【NetCore】使用表达式目录树实现动态组装Where的Linq表达式
代码仓库:https://gitee.com/wosperry/perry-expression-practice.git
如果想调试的话,可以安装git后,在控制台运行 git clone https://gitee.com/wosperry/perry-expression-practice.git
获取到代码,直接运行控制台程序即可(类库项目即是NuGet的那个代码)。
上一篇使用表达式目录树实现根据参数类的配置,动态构建Lambda表达式。后面在老张的哲学弄的那个技术群里,群友给建议,让我把枚举值去掉,换成多个Attribute,仔细一想感觉是很有道理。我自己用的时候我也不希望写个特性还非要带一个要指定变量名的又臭又长的参数。
于是就着手去改。花了两个小时,把这些改完了并第一次尝试发布到NuGet,然后把控制台程序修改为安装NuGet包,一次成功,蛮开心的。同时为了配置NuGet里的几个参数,顺便把Gitee项目设置为了Apache2.0开源了。
已经发布到NuGet,安装命令
# 程序包管理控制台 Install-Package Wosperry.ExpressionExtensions -Version 1.0.2 # .Net CLI dotnet add package Wosperry.ExpressionExtensions --version 1.0.2 # PackageReference XML <PackageReference Include="Wosperry.ExpressionExtensions" Version="1.0.2" />
使用参考
- 实体类和参数类:
using Wosperry.ExpressionExtensions.Attributes; namespace ConsoleApp { public class Student { public string Name { get; set; } public string Code { get; set; } public int? Age { get; set; } } public class StudentListQueryParameter { [WhereLike] public string Name { get; set; } [WhereLike("Code")] public string Number { get; set; } [WhereEqual] public int? Age { get; set; } } }
- 使用
// 需要引用: using Wosperry.ExpressionExtensions.Extends; #region 假数据 var input = new StudentListQueryParameter() { //Age = 18, Number = "B00", // Name = "张" }; List<Student> students = new List<Student> { new Student{ Code="A001",Name="张三",Age=25}, new Student{ Code="A002",Name="李四",Age=18}, new Student{ Code="A003",Name="王五",Age=10}, new Student{ Code="B001",Name="张四",Age=18}, new Student{ Code="B002",Name="李五",Age=12}, new Student{ Code="B003",Name="王六",Age=45}, new Student{ Code="C001",Name="张五",Age=22}, new Student{ Code="C001",Name="李六",Age=18}, new Student{ Code="C001",Name="王七",Age=20}, }; #endregion // 使用 var query = students.AsQueryable(); var data = query.Where(query.BuildLambda(input)).ToList(); // 如果是ABP的IRepository, 默认实现了IQueryable,所以调用如: // var query = _repository.Where(_repository.BuildLambda(input)); // var data = await AsyncExecuter.ToListAsync(query);
展示一下调整后的代码,同样是希望能够帮助到未来的自己,还有暂时没有接触过这个东西的同行们。
事实上代码没有那么多,只是注释太密集了,没办法,我怕过两天我自己看不懂,多写了点注释,如果不想看那么多注释,可以拷贝出去删掉看。
public static class BinaryExpressionExtensions { /// <summary> /// 连接一个Like(字符串的Contains) /// </summary> /// <param name="resultExpression">表达式</param> /// <param name="field">实体属性/字段</param> /// <param name="valueToCompare">对比的值</param> /// <param name="stringComparison">字符串对比规则</param> /// <returns> 返回示例: xxx && t.Contains(valueToCompare)</returns> public static BinaryExpression AndLikeLambda(this BinaryExpression resultExpression, MemberExpression field, ConstantExpression valueToCompare, StringComparison stringComparison = default) { // Contains 方法 var containMethod = typeof(string).GetMethod( nameof(string.Contains), new Type[] { typeof(string), typeof(StringComparison) } ); // 表达式:Contains 方法 var containMethodExpression = Expression.Call( field, containMethod, valueToCompare, Expression.Constant(stringComparison) ); return Expression.AndAlso(resultExpression, containMethodExpression); } /// <summary> /// 连接一个 Equals /// </summary> /// <param name="resultExpression"></param> /// <param name="field"></param> /// <param name="valueToCompare"></param> /// <returns></returns> public static BinaryExpression AndEqualLambda(this BinaryExpression resultExpression, MemberExpression field, ConstantExpression valueToCompare) { return Expression.AndAlso( resultExpression, Expression.Equal( field, Expression.Convert(valueToCompare, field.Type) ) ); } }
public static class IQuaryableExtension { /// <summary> /// 生成查询条件 /// </summary> /// <typeparam name="TQueryParams">查询参数对象</typeparam> /// <param name="queryable">原有IQueryable</param> /// <exception cref="WhereAttribute.Field"> /// 当 WhereAttribute.Field 指定的字段名在TEntity类型中不存在的时候,抛出异常 /// </exception> /// <returns>lambda 表达式</returns> public static Expression<Func<TEntity, bool>> BuildLambda<TEntity, TQueryParams>(this IQueryable<TEntity> query, TQueryParams input, Action<BuildWhereOptions> options = null) where TEntity : class { // 配置项 BuildWhereOptions buildWhereOptions = new BuildWhereOptions(); if (!(options is null)) { options(buildWhereOptions); } var t = Expression.Parameter(typeof(TEntity), "t"); // 表达式:true var trueExpression = Expression.Constant(true); // 表达式:true && true var result = Expression.AndAlso(trueExpression, trueExpression); // 遍历入参所有属性 foreach (var prop in typeof(TQueryParams).GetProperties()) { // 根据特性分别处理 var attrs = prop.GetCustomAttributes(); // 如果没有任何特性,则使用默认 DefaultAttribute foreach (WhereAttribute attribute in attrs.Where(w => w is WhereAttribute)) { // 表达式:实体属性 t // 当attr未指定 Field 值的时候,默认为与入参同名 // 党attr指定了 Field 值的时候,使用 Field if (string.IsNullOrWhiteSpace(attribute.Field)) { attribute.Field = prop.Name; } // 对比的参数为空时,不做处理 var valueToCompare = prop.GetValue(input); if (valueToCompare is null) continue; // string 时,单独判断一次是否是空值 if (prop.PropertyType == typeof(string) && string.IsNullOrWhiteSpace(valueToCompare as string)) continue; // 表达式实体属性:t.Name var fieldExpression = Expression.Property(t, attribute.Field); // 需要对比的值:value var valueExpression = Expression.Constant(valueToCompare, prop.PropertyType); #region 构建表达式 // 相等 // t.Name.Equals(value) if (attribute is WhereEqualAttribute) { result = result.AndEqualLambda(fieldExpression, valueExpression); } // Like(字符串的Contains) // t.Name.Contains(value, builderWhereOptions.StringComparison) if (attribute is WhereLikeAttribute) { result = result.AndLikeLambda(fieldExpression, valueExpression, buildWhereOptions.StringComparison); } // TODO:增加其他的对比类型(Larger、Less、In) #endregion } } // 如:t=>t.Age.Equals(input.Age) && t.Code.Contains(input.Number) && t.Name.Contains(input.Name) // 注意:input.Number是因为其有特性 [WhereLike("Code")] return Expression.Lambda<Func<TEntity, bool>>(result, t); } }
这篇关于【NetCore】调整表达式目录树实现并发布到NuGet的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2022-03-01沐雪多租宝商城源码从.NetCore3.1升级到.Net6的步骤
- 2024-12-06使用Microsoft.Extensions.AI在.NET中生成嵌入向量
- 2024-11-18微软研究:RAG系统的四个层次提升理解与回答能力
- 2024-11-15C#中怎么从PEM格式的证书中提取公钥?-icode9专业技术文章分享
- 2024-11-14云架构设计——如何用diagrams.net绘制专业的AWS架构图?
- 2024-05-08首个适配Visual Studio平台的国产智能编程助手CodeGeeX正式上线!C#程序员必备效率神器!
- 2024-03-30C#设计模式之十六迭代器模式(Iterator Pattern)【行为型】
- 2024-03-29c# datetime tryparse
- 2024-02-21list find index c#
- 2024-01-24convert toint32 c#