场景

从接口返回的数据是集合,却是 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. windows下安装mysql5.6.47版本

    详情转载地址:https://www.cnblogs.com/alan-lin/p/9966917.html

  2. Spring-Boot注入自定义properties文件配置

    创建wzq.properties wzq.properties注入User实体类中 @PropertySource(value = "classpath:wzq.properties&quo ...

  3. C#用SOCKET发送HTTP请求小例

    private void button1_Click(object sender, EventArgs e) { string urlStr = this.textUrl.Text ; if (url ...

  4. JavaWeb学习总结—Session

    转载自:https://www.cnblogs.com/xdp-gacl/p/3855702.html 一.Session简单介绍 在WEB开发中,服务器可以为每个用户浏览器创建一个会话对象(sess ...

  5. Java中Byte类型数据在运算中的问题

    比如: byte a=1; byte b=2; byte c; c=a+b; //这样是计算不出c,是错误的 c=a+1; //这样也是不能计算c的 c=64+1; //为什么这样就能计算c,在Jav ...

  6. jQuery中的文档操作处理(五):append()、prepend()、after()、before()、wrap()、wrapAll()、wrapInner()、clone()等

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <hea ...

  7. linux 常用命令(三)——(centos7)MySql 5.7添加用户、删除用户与授权

    一.创建用户:以root用户登录到数据库进行用户创建 命令: CREATE USER 'username'@'host' IDENTIFIED BY 'password'; 例如: CREATE US ...

  8. Hibernate之抓取策略

    时间:2017-1-23 19:08 --区分延迟和立即检索1.立即检索    当执行某行代码时,会马上发出SQL语句进行查询.    例如:get()2.延迟检索    当执行某行代码时,不会马上发 ...

  9. 设计模式<一>

    设计原则1.找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起. 2.针对接口编程,而不是针对实现编程. 3.多用组合,少用继承. 一:策略模式,定义了算法族,分别封装起来 ...

  10. vue@cli3 项目模板怎么使用public目录下的静态文件,找了好久都不对,郁闷!

    作为图片最好放在static目录下,但是vue@cli3没有static,网上都说放在public目录下,行,那就放吧,可问题是图片放了怎么使用 第一次尝试 肯定用绝对路径这就不说了,用相对路径,we ...