• Expression Tree 遍历集合


    场景

    从接口返回的数据是集合,却是 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)}");
    }
    本博客内容,如需转载请务必保留超链接。

    Contact Me:Mail此处省略好几个字...
  • 相关阅读:
    Atitit 人脸识别 眼睛形态 attilax总结
    Atitit 手机号码选号 规范 流程 attilax总结 v2 r99.docx
    atitit 板块分类 上市公司 龙头企业公司 列表 attilax总结.docx
    Atititi atiitt eam pam资产管理 购物表去年.xlsx
    使用cmd查看电脑连接过的wifi密码(一)
    常见十大web攻击手段 悟寰轩
    常见web攻击方式 悟寰轩
    【MYSQL数据库】MYSQL学习笔记mysql分区基本操作 悟寰轩
    Filter及FilterChain的使用详解 悟寰轩
    启动tomcat spring初始化两次问题(eg:@PostConstruct) 悟寰轩
  • 原文地址:https://www.cnblogs.com/jroger/p/15192361.html
Copyright © 2020-2023  润新知