场景

从接口返回的数据是集合,却是 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. windows10磁盘分区后,如何恢复分区,回到未分区之前

    windows10磁盘分区后,恢复到分区以前的状态 1.我的电脑右键======>管理 2.找到磁盘管理 3.因为我的H盘原来是和F盘是同一个分区,只是拆分出来了,所有,找到H盘(确保数据都做过 ...

  2. spring开发中常见错误集合,逐步添加

    1.关于jstl错误:原因,在jsp页面中使用了jstl标签库,但是却没有导入,可以将相应的jar包放在tomcat的lib目录下,一劳永逸 Java.lang.NoClassDefFoundErro ...

  3. ASP.NET Core Web API接收文件传输

    ASP.NET解析API参数的方式有很多种,包括[FromBody],[FromForm],[FromServices],[FromHeader][FromQuery]. 文件传输方式也分很多种,包括 ...

  4. LeetCoded第20题题解--有效的括号

    有效的括号 给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效. 有效字符串需满足: 左括号必须用相同类型的右括号闭合. 左括号必须以正确的顺序闭合. 注意空 ...

  5. 刷题-力扣-264. 丑数 II

    264. 丑数 II 题目链接 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/ugly-number-ii/ 著作权归领扣网络所有.商业转载请 ...

  6. springcloud <zuul2.0静态配置>

    server: port: 9006 spring: application: name: cloud-zuul-wangbiao # zipkin: # base-url: http://local ...

  7. MySQL-存储引擎-MERGE

    MERGE存储引擎是一组Myisam表的组合,这些Myisam表必须结构完全相同,MERGE表本身并没有数据,对MERGE类型的表可以进行查询.更新.删除操作,这些操作实际上是对内部的Myisam表进 ...

  8. python variable scope 变量作用域

    python 中变量的作用域经常让我感到很迷 In Python, on the other hand, variables declared in if-statements, for-loop b ...

  9. vue2+vite初体验

    前言 自从 vite 发布之后,社区赞誉无数,而我也一直心水 vite 的轻量快速的热重载的特性,特别是公司的项目巨大,已经严重拖慢了热重载的速度了,每次热重载都要等上一小会,所以急需寻找一个解决方案 ...

  10. AspectJ——AOP框架快速入门

    一.导包 二.bean.xml配置 三.环绕通知 四,表达式