using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; namespace CPF.Windows.Json.Deserialize { [ExpressionBuildType(DeserializeBuildTypeEnum.MultiArray)] internal class MultiArrayBuild : ExpressionJsonResolve { internal static BlockExpression Build(Type multiType, Type sawtoothType, int rank) { LabelTarget returnValueLable = Expression.Label(multiType, "returnValue"); List lambdaVariables = new List(); Expression[] exs = new Expression[3]; ParameterExpression sawtoothAry = Expression.Variable(sawtoothType); lambdaVariables.Add(sawtoothAry); /* int[][][] sawtoothAry= InvokeGet(); */ exs[0] = Expression.Assign(sawtoothAry, ExpressionMembers.GetMethodCall(sawtoothType)); /* if(sawtoothAry==null) return null; else ... */ exs[1] = Expression.IfThenElse( Expression.Equal(sawtoothAry, Expression.Constant(null, sawtoothType)), Expression.Return(returnValueLable, Expression.Constant(null, multiType)), ReturnFunc(() => { List expressions = new List(); /* var index0_Length = sawtoothAry.Length; var index1_Length = sawtoothAry[0].Length; var index2_Length = sawtoothAry[0][0].Length; var a = 0; var b = 0; var c = 0; */ ParameterExpression[] arrayLengthVariables = new ParameterExpression[rank]; ParameterExpression[] forVariables = new ParameterExpression[rank]; for (int i = 0; i < arrayLengthVariables.Length; i++) { arrayLengthVariables[i] = Expression.Variable(typeof(int)); expressions.Add(Expression.Assign(arrayLengthVariables[i], Expression.MakeMemberAccess(GetIndexAccessBySawtoothAry(sawtoothAry, GetExpressionConstantZero(i).ToArray()), typeof(Array).GetProperty("Length")))); forVariables[i] = Expression.Variable(typeof(int)); } lambdaVariables.AddRange(arrayLengthVariables); /* int[,,] multiAry=new multiAry(index0_Length,index1_Length,index2_Length) */ ParameterExpression multiAry = Expression.Variable(multiType); lambdaVariables.Add(multiAry); expressions.Add(Expression.Assign(multiAry, Expression.New(multiType.GetConstructors()[0], arrayLengthVariables))); /* for (int a = 0; a < index0_Length; a++) { for (int b = 0; b < index1_Length; b++) { for (int c = 0; c < index2_Length; c++) { multiAry[a,b,c] = sawtoothAry[a][b][c]; } } } */ Expression forMain = null; for (int i = arrayLengthVariables.Length - 1; i >= 0; i--) { Expression content = null; if (forMain == null) { /* sawtoothAry[a][b][c]; */ Expression sawtoothAryAccess = GetIndexAccessBySawtoothAry(sawtoothAry, forVariables); /* multiAry[a,b,c] = sawtoothAry[a][b][c]; */ content = Expression.Assign(Expression.ArrayAccess(multiAry, forVariables), sawtoothAryAccess); } else content = forMain; forMain = ExpressionHelper.For(forVariables[i], Expression.LessThan(forVariables[i], arrayLengthVariables[i]), Expression.PostIncrementAssign(forVariables[i]), content ); } expressions.Add(forMain); /* return multiAry */ expressions.Add(Expression.Return(returnValueLable, multiAry)); return Expression.Block(expressions); })); exs[2] = Expression.Label(returnValueLable, Expression.Constant(null, multiType)); return Expression.Block(lambdaVariables.ToArray(), exs); } internal static IEnumerable GetExpressionConstantZero(int num) { for (int i = 0; i < num; i++) { yield return Expression.Constant(0); } } internal static Expression GetIndexAccessBySawtoothAry(ParameterExpression sawtoothAry, Expression[] indexs) { if (!indexs.Any()) return sawtoothAry; Expression lastAccess = null; foreach (var t in indexs) { lastAccess = Expression.ArrayAccess(lastAccess ?? sawtoothAry, t); } return lastAccess; } } }