场景

从接口返回的数据是集合,却是 object 类型的。这个时候需要遍历这个集合。现提供两种方法。

方法一:

因为集合是可枚举的,所以可以尝试转为 IEnumerable 类型,然后遍历即可。

static void Main(string[] args)
{
var list = new List<Foo> {
new Foo{ Id = 1, Name = "aaa" },
new Foo{ Id = 2, Name = "bbb" },
new Foo{ Id = 3, Name = "ccc" }
}; ReflectionCollection(list);
} private static void ReflectionCollection(object input)
{
var collection = input as IEnumerable;
if (collection is not null)
{
var enumerator = collection.GetEnumerator();
while (enumerator.MoveNext())
{
Console.WriteLine($"{JsonSerializer.Serialize(enumerator.Current)}");
}
}
}

方法二:

使用表达式树。

private static void ExpressionTreeAccessCollection(object input)
{
var type = input.GetType();
var inputParameterExp = Expression.Parameter(typeof(object), "input");
var callbackParameterExp = Expression.Parameter(typeof(Action<object>), "callback");
var countVariableExp = Expression.Variable(typeof(int), "count");
var tempVariableExp = Expression.Variable(typeof(int));
var itemVariableExp = Expression.Variable(typeof(object), "item");
var convertExp = Expression.Convert(inputParameterExp, type);
var voidLabel = Expression.Label(); // 方法一
var indexProperty = type.GetDefaultMembers().OfType<PropertyInfo>()
.First(_ => _.GetIndexParameters().Any(_ => _.ParameterType == typeof(int))); // 方法二
//var toArrayMethod = type.GetMethod(nameof(List<object>.ToArray));
//var toArrayExp = Expression.Call(convertExp, toArrayMethod);
//var arrayIndexExp = Expression.ArrayIndex(toArrayExp, new Expression[] { tempVariableExp }); // 调用外部方法
//var printItemMethod = typeof(Program).GetMethod(nameof(PrintItem), BindingFlags.NonPublic | BindingFlags.Static); var blockExp = Expression.Block(
new ParameterExpression[] { countVariableExp, tempVariableExp, itemVariableExp },
Expression.Assign(
countVariableExp,
Expression.Property(convertExp, "Count")
),
Expression.Assign(tempVariableExp, Expression.Constant(0)),
Expression.Loop(
Expression.IfThenElse(
Expression.LessThan(tempVariableExp, countVariableExp),
Expression.Block(
new ParameterExpression[] { itemVariableExp },
// 方法一
Expression.Assign(itemVariableExp, Expression.MakeIndex(convertExp, indexProperty, new ParameterExpression[] { tempVariableExp })), // 方法二
//Expression.Assign(itemVariableExp, arrayIndexExp), // 调用外部方法
//Expression.Call(null, printItemMethod, itemVariableExp), // 调用回调函数
Expression.Invoke(callbackParameterExp, itemVariableExp),
Expression.AddAssign(tempVariableExp, Expression.Constant(1, typeof(int)))
),
Expression.Block(
Expression.Return(voidLabel)
)
)
),
Expression.Label(voidLabel)
); var lambda = Expression.Lambda<Action<object, Action<object>>>(blockExp, new ParameterExpression[] { inputParameterExp, callbackParameterExp });
var func = lambda.Compile();
func(input, item => {
Console.WriteLine($"Callback: {JsonSerializer.Serialize(item)}");
});
} private static void PrintItem(object item)
{
Console.WriteLine($"PrintItem: {JsonSerializer.Serialize(item)}");
}

Expression Tree 遍历集合的更多相关文章

  1. Reflection和Expression Tree解析泛型集合快速定制特殊格式的Json

    很多项目都会用到Json,而且大部分的Json都是格式固定,功能强大,转换简单等,标准的key,value集合字符串:直接JsonConvert.SerializeObject(List<T&g ...

  2. 【C#表达式树 开篇】 Expression Tree - 动态语言

    .NET 3.5中新增的表达式树(Expression Tree)特性,第一次在.NET平台中引入了"逻辑即数据"的概念.也就是说,我们可以在代码里使用高级语言的形式编写一段逻辑, ...

  3. 深入学习C#匿名函数、委托、Lambda表达式、表达式树类型——Expression tree types

    匿名函数 匿名函数(Anonymous Function)是表示“内联”方法定义的表达式.匿名函数本身及其内部没有值或者类型,但是可以转换为兼容的委托或者表达式树类型(了解详情).匿名函数转换的计算取 ...

  4. Lambda表达式遍历集合

    1.Collection Java 8 为Iterable接口新增了一个forEach(Consumer action)默认方法,该方法所需参数的类型是一个函数式接口,而Iterable接口是Coll ...

  5. Expression Tree Basics 表达式树原理

    variable point to code variable expression tree data structure lamda expression anonymous function 原 ...

  6. Expression Tree 扩展MVC中的 HtmlHelper 和 UrlHelper

    表达式树是LINQ To everything 的基础,同时各种类库的Fluent API也 大量使用了Expression Tree.还记得我在不懂expression tree时,各种眼花缭乱的A ...

  7. 使用Expression Tree构建动态LINQ查询

    这篇文章介绍一个有意思的话题,也是经常被人问到的:如何构建动态LINQ查询?所谓动态,主要的意思在于查询的条件可以随机组合,动态添加,而不是固定的写法.这个在很多系统开发过程中是非常有用的. 我这里给 ...

  8. JAVA基础学习之final关键字、遍历集合、日期类对象的使用、Math类对象的使用、Runtime类对象的使用、时间对象Date(两个日期相减)(5)

    1.final关键字和.net中的const关键字一样,是常量的修饰符,但是final还可以修饰类.方法.写法规范:常量所有字母都大写,多个单词中间用 "_"连接. 2.遍历集合A ...

  9. .NET Expression Tree

    Expression Tree 第一个简单的例子. [TestMethod] public void GodTest() { Expression<Func<int, int, int&g ...

随机推荐

  1. SpringBoot启动标识修改

    在src/main/resources下新建一个banner.txt ${AnsiColor.BRIGHT_RED} ///////////////////////////////////////// ...

  2. Java全家桶的这些知识,不用学了

    众所周知,Java 的知识体系繁冗复杂,但是有很多知识在实际工作中几乎没有人用. 很多人在学习过程中,却经常把有限的时间和精力花在了这些"没有用"的知识上,事倍功半. 下面我捋一捋 ...

  3. WebAPI 自定义过滤

    自定义filter 类过滤 ------------------------------------------------------------------------- public class ...

  4. Spring第一课:依赖注入DI(二)

    DI Dependency Injection ,依赖注入 is a :是一个,继承. has a:有一个,成员变量,依赖. class B { private A a;   //B类依赖A类 } 依 ...

  5. 模拟文件上传(二):使用apache fileupload组件进行文件上传

    其中涉及到的jar包: jsp显示层: <%@ page language="java" import="java.util.*" pageEncodin ...

  6. 如何从 vue-element-admin 迁移到 Fantastic-admin

    // FIXME 链接更新 如果你还不知道 Fantastic-admin 是什么,那么我先用几张预览图给大家了解一番. 看来预览图,如果你感兴趣,可以点这里来详细了解并试用,这是一款完成度极高,开箱 ...

  7. Blazor+Dapr+K8s微服务之基于WSL安装K8s集群并部署微服务

         前面文章已经演示过,将我们的示例微服务程序DaprTest1部署到k8s上并运行.当时用的k8s是Docker for desktop 自带的k8s,只要在Docker for deskto ...

  8. Hadoop及Hbase部署

    原文转自:https://www.cnblogs.com/itzgr/p/10233932.html作者:木二 目录 一 环境准备 1.1 相关环境 1.2 网络环境 二 基础环境配置 2.1 配置相 ...

  9. golang GC 垃圾回收机制

    垃圾回收(Garbage Collection,简称GC)是编程语言中提供的自动的内存管理机制,自动释放不需要的对象,让出存储器资源,无需程序员手动执行. Golang中的垃圾回收主要应用三色标记法, ...

  10. Redis的读写分离

    1.概述 随着企业业务的不断扩大,请求的并发量不断增长,Redis可能终会出现无法负载的情况,此时我们就需要想办法去提升Redis的负载能力. 读写分离(主从复制)是一个比较简单的扩展方案,使用多台机 ...