zoukankan      html  css  js  c++  java
  • 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此处省略好几个字...
  • 相关阅读:
    USACO Milk2 区间合并
    Codeforces 490B Queue【模拟】
    HDU 3974 Assign the task 简单搜索
    HDU 5119 Happy Matt Friends(2014北京区域赛现场赛H题 裸背包DP)
    Cin、Cout 加快效率方法
    POJ 1159 回文LCS滚动数组优化
    POJ 2479 不相交最大子段和
    POJ 1458 最长公共子序列 LCS
    在阿里最深刻的,还是职场之道给我的震撼
    精细化
  • 原文地址:https://www.cnblogs.com/jroger/p/15192361.html
Copyright © 2011-2022 走看看