using System; using System.Linq.Expressions; namespace CPF.Windows.Json.Deserialize { [ExpressionBuildType(DeserializeBuildTypeEnum.Array)] internal class ArrayBuild : ExpressionJsonResolve { internal static BlockExpression Build(Type type) { Type arrayItemType = type.GetElementType(); Expression[] methodListCall = new Expression[11]; LabelTarget returnTarget = Expression.Label(type, "returnLable"); /* if (reader.ReadNullOrArrayLeft()) return null; */ Expression ifReadNullOrArrayLeftReturnNull = Expression.IfThen(Expression.Call(ExpressionMembers.Reader, JsonReader._ReadNullOrArrayLeft), Expression.Return(returnTarget, Expression.Constant(null, type))); methodListCall[0] = ifReadNullOrArrayLeftReturnNull; /* int arrayLength=reader._GetArrayLength; T[] array=new [arrayLength]; */ ParameterExpression arrayLength = Expression.Variable(typeof(int), "arrayLength"); methodListCall[1] = Expression.Assign(arrayLength, Expression.Call(ExpressionMembers.Reader, JsonReader._GetArrayLength, ExpressionMembers.JsonDeserializeHandler)); NewExpression aryCtor = Expression.New(type.GetConstructors()[0], arrayLength); ParameterExpression array = Expression.Variable(type, "array"); methodListCall[2] = Expression.Assign(array, aryCtor); /* if(arrayLength==0) goto ReadArrayRightLabel; */ LabelTarget readArrayRightLabel = Expression.Label(typeof(void), "ReadArrayRightLabel"); methodListCall[3] = Expression.IfThen(Expression.Equal(arrayLength, Expression.Constant(0)), Expression.Goto(readArrayRightLabel)); /* int moveNext=1; */ methodListCall[4] = ExpressionMembers.MoveNextAssignOne; /* int idx=0; */ ParameterExpression idx = Expression.Variable(typeof(int), "idx"); methodListCall[5] = Expression.Assign(idx, Expression.Constant(0)); /* while(moveNext-->0) {} */ LabelTarget loopBreak = Expression.Label("loopBreak"); LoopExpression loopExpression = Expression.Loop(Expression.IfThenElse(ExpressionMembers.MoveNextDecrement, ReturnFunc(() => { Expression[] methodCall = new Expression[3]; /* ary[idx]=item; */ methodCall[0] = Expression.Assign(Expression.ArrayAccess(array, idx), ExpressionMembers.GetMethodCall(arrayItemType)); /* if(reader.ReadBoolComma()==true) moveNext++; */ methodCall[1] = ExpressionMembers.IfReadBoolCommaIsTrueSoMoveNextIncrement; /* idx++; */ methodCall[2] = Expression.PostIncrementAssign(idx); return Expression.Block(methodCall); ; }) , Expression.Break(loopBreak))); methodListCall[6] = Expression.Block(loopExpression, Expression.Label(loopBreak)); /* ReadArrayRightLabel: reader.ReadArrayRight() */ methodListCall[7] = Expression.Label(readArrayRightLabel); methodListCall[8] = Expression.Call(ExpressionMembers.Reader, JsonReader._ReadArrayRight); /* return list; */ GotoExpression returnExpression = Expression.Return(returnTarget, array); LabelExpression returnLabel = Expression.Label(returnTarget, array); methodListCall[9] = returnExpression; methodListCall[10] = returnLabel; return Expression.Block(new[] { arrayLength, array, idx, ExpressionMembers.MoveNext }, methodListCall); } } }