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此处省略好几个字...