VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > temp > 简明python教程 >
  • 动态构造任意复杂的 Linq Where 表达式(3)

ni": //不属于(不是候选值列表之一) 321 e = Expression.Not(BuildContainsExpression(rule, l, pt)); 322 break; 323 case "nu": //为空 324 r = Expression.Constant(null); 325 e = Expression.Equal(l, r); 326 break; 327 case "nn": //不为空 328 r = Expression.Constant(null); 329 e = Expression.Not(Expression.Equal(l, r)); 330 break; 331 case "bt": //区间 332 throw new NotImplementedException($"尚未实现创建{rule.Op}类型的比较表达式"); 333 default: 334 throw new InvalidOperationException($"不支持创建{rule.Op}类型的比较表达式"); 335 } 336 337 return e; 338 339 static Expression BuildConstantExpression<TValue>(JqGridSearchRule jRule, Func<string, TValue> valueConvertor) 340 { 341 var rv = valueConvertor(jRule.Data); 342 return Expression.Constant(rv); 343 } 344 } 345 346 /// <summary> 347 /// 构造Contains调用表达式 348 /// </summary> 349 /// <param name="rule">条件</param> 350 /// <param name="parameter">参数</param> 351 /// <param name="parameterType">参数类型</param> 352 /// <returns>Contains调用表达式</returns> 353 private static Expression BuildContainsExpression(JqGridSearchRule rule, Expression parameter, Type parameterType) 354 { 355 Expression e = null; 356 357 var genMethod = typeof(Queryable).GetMethods() 358 .Single(m => m.Name == nameof(Queryable.Contains) && m.GetParameters().Length == 2); 359 360 var jsonArray = JsonSerializer.Deserialize<string[]>(rule.Data); 361 362 switch (parameterType) 363 { 364 #region 文字 365 366 case Type ct when ct == typeof(char): 367 if (jsonArray.Any(o => o.Length != 1)) {throw new InvalidOperationException("字符型的候选列表中存在错误的候选项");} 368 e = CallContains(parameter, jsonArray, str => str[0], genMethod, ct); 369 break; 370 case Type ct when ct == typeof(string): 371 e = CallContains(parameter, jsonArray, str => str, genMethod, ct); 372 break; 373 374 #endregion 375 376 #region 有符号整数 377 378 case Type ct when ct == typeof(sbyte): 379 e = CallContains(parameter, jsonArray, sbyte.Parse, genMethod, ct); 380 break; 381 case Type ct when ct == typeof(short): 382 e = CallContains(parameter, jsonArray, short.Parse, genMethod, ct); 383 break; 384 case Type ct when ct == typeof(int): 385 e = CallContains(parameter, jsonArray, int.Parse, genMethod, ct); 386 break; 387 case Type ct when ct == typeof(long): 388 e = CallContains(parameter, jsonArray, long.Parse, genMethod, ct); 389 break; 390 391 #endregion 392 393 #region 无符号整数 394 395 case Type ct when ct == typeof(byte): 396 e = CallContains(parameter, jsonArray, byte.Parse, genMethod, ct); 397 break; 398 case Type ct when ct == typeof(ushort): 399 e = CallContains(parameter, jsonArray, ushort.Parse, genMethod, ct); 400 break; 401 case Type ct when ct == typeof(uint): 402 e = CallContains(parameter, jsonArray, uint.Parse, genMethod, ct); 403 break; 404 case Type ct when ct == typeof(ulong): 405 e = CallContains(parameter, jsonArray, ulong.Parse, genMethod, ct); 406 break; 407 408 #endregion 409 410 #region 小数 411 412 case Type ct when ct == typeof(float): 413 e = CallContains(parameter, jsonArray, float.Parse, genMethod, ct); 414 break; 415 case Type ct when ct == typeof(double): 416 e = CallContains(parameter, jsonArray, double.Parse, genMethod, ct); 417 break; 418 case Type ct when ct == typeof(decimal): 419 e = CallContains(parameter, jsonArray, decimal.Parse, genMethod, ct); 420 break; 421 422 #endregion 423 424 #region 其它常用类型 425 426 case Type ct when ct == typeof(DateTime): 427 e = CallContains(parameter, jsonArray, DateTime.Parse, genMethod, ct); 428 break; 429 case Type ct when ct == typeof(DateTimeOffset): 430 e = CallContains(parameter, jsonArray, DateTimeOffset.Parse, genMethod, ct); 431 break; 432 case Type ct when ct == typeof(Guid): 433 e = CallContains(parameter, jsonArray, Guid.Parse, genMethod, ct); 434 break; 435 case Type ct when ct.IsEnum: 436 e = CallContains(Expression.Convert(parameter, typeof(object)), jsonArray, enumString => enumString.ToEnumObject(ct), genMethod, ct); 437 break; 438 439 #endregion 440 } 441 442 return e; 443 444 static MethodCallExpression CallContains<T>(Expression pa, string[] jArray, Func<string, T> selector, MethodInfo genericMethod, Type type) 445 { 446 var data = jArray.Select(selector).ToArray().AsQueryable(); 447 var method = genericMethod.MakeGenericMethod(type); 448 449 return Expression.Call(null, method, new[] { Expression.Constant(data), pa }); 450 } 451 } 452 }
复制代码

使用

       此处是在 Razor Page 中使用,内部使用的其他辅助类和前端页面代码就不贴了,有兴趣的可以在我的文章末尾找到 GitHub 项目链接:

复制代码
复制代码
 1         public async Task<IActionResult> OnGetUserListAsync([FromQuery]JqGridParameter jqGridParameter)
 2         {
 3             var usersQuery = _userManager.Users.AsNoTracking();
 4             if (jqGridParameter._search == "true")
 5             {
 6                 usersQuery = usersQuery.Where(BuildWhere<ApplicationUser>(jqGridParameter.FilterObject, null));
 7             }
 8 
 9             var users = usersQuery.Include(u => u.UserRoles).ThenInclude(ur => ur.Role).OrderBy(u => u.InsertOrder)
10                 .Skip((jqGridParameter.Page - 1) * jqGridParameter.Rows).Take(jqGridParameter.Rows).ToList();
11             var userCount = usersQuery.Count();
12             var pageCount = Ceiling((double) userCount / jqGridParameter.Rows);
13             return new JsonResult(
14                 new
15                 {
16                     rows //数据集合
17                         = users.Select(u => new
18                         {
19                             u.UserName,
20                             u.Gender,
21                             u.Email,
22                             u.PhoneNumber,
23                             u.EmailConfirmed,
24                             u.PhoneNumberConfirmed,
25                             u.CreationTime,
26                             u.CreatorId,
27                             u.Active,
28                             u.LastModificationTime,
29                             u.LastModifierId,
30                             u.InsertOrder,
31                             u.ConcurrencyStamp,
32                             //以下为JqGrid中必须的字段
33                             u.Id //记录的唯一标识,可在插件中配置为其它字段,但是必须能作为记录的唯一标识用,不能重复
34                         }),
35                     total = pageCount, //总页数
36                     page = jqGridParameter.Page, //当前页码
37                     records = userCount //总记录数
38                 }
39             );
40         }
复制代码

       启动项目后访问 /Identity/Manage/Users/Index 可以尝试使用。

结语

       通过这次实践,深入了解了很多表达式树的相关知识,表达式树在编译流程中还算是高级结构了,耐点心还是能看懂,IL 才是真的晕,比原生汇编也好不到哪里去。C# 确实很有意思,入门简单,内部却深邃无比,在小白和大神手上完全是两种语言。Java 在 Java 8 时增加了 Stream 和 Lambda 表达式功能,一看就是在对标 Linq,不过那名字取的真是一言难尽,看代码写代码感觉如鲠在喉,相当不爽。由于 Stream 体系缺少表达式树,这种动态构造查询表达式的功能从一开始就不可能支持。再加上 Java 没有匿名类型,没有对象初始化器,每次用 Stream 就难受的一批,中间过程的数据结构也要专门写类,每个中间类还要独占一个文件,简直晕死。抄都抄不及格!

       C# 引入 var 关键字核心是为匿名类型服务,毕竟是编译器自动生成的类型,写代码的时候根本没有名字,不用 var 用什么?简化变量初始化代码只是顺带的。结果 Java 又抄一半,还是最不打紧的一半,简化变量初始化代码。真不知道搞 Java 的那帮人在想些什么。

 

       转载请完整保留以下内容并在显眼位置标注,未经授权删除以下内容进行转载盗用的,保留追究法律责任的权利!

  本文地址:https://www.cnblogs.com/coredx/p/12423929.html

  完整源代码:Github

  里面有各种小东西,这只是其中之一,不嫌弃的话可以Star一下。


相关教程
          
关于我们--广告服务--免责声明--本站帮助-友情链接--版权声明--联系我们       黑ICP备07002182号