• 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此处省略好几个字...
  • 相关阅读:
    Pyhton学习——Day60
    Pyhton学习——Day58
    Python——微信数据分析
    C/C++文件指针偏移
    I/O流+统计文件词频
    vector概念
    new/delete工作机制
    Singleton单例类模式
    对象数组
    特殊成员函数
  • 原文地址:https://www.cnblogs.com/jroger/p/15192361.html
Copyright © 2020-2023  润新知