using System; using System.Collections.Generic; using System.Linq.Expressions; namespace CPF.Windows.Json.Deserialize { [ExpressionBuildType(DeserializeBuildTypeEnum.Dynamic)] internal class DynamicBuild : ExpressionJsonResolve { internal static BlockExpression Build(Type type) { List methodCall = new List(); LabelTarget returnValueLable = Expression.Label(type, "returnValue"); var c = type.GetProperties(); ParameterExpression[] ctorArgs = null; if (c.Length > 0) { ctorArgs = new ParameterExpression[c.Length]; for (int i = 0; i < c.Length; i++) { ctorArgs[i] = Expression.Variable(c[i].PropertyType); if (c[i].PropertyType.IsValueType) methodCall.Add(Expression.Assign(ctorArgs[i], Expression.New(c[i].PropertyType))); else methodCall.Add(Expression.Assign(ctorArgs[i], Expression.Constant(null, c[i].PropertyType))); } } methodCall.Add(Expression.IfThen(Expression.Call(ExpressionMembers.Reader, JsonReader._ReadNullOrObjLeft), Expression.Return(returnValueLable, Expression.Constant(null, type)))); methodCall.Add(Expression.IfThen(Expression.Call(ExpressionMembers.Reader, JsonReader._ReadBoolObjRight), Expression.Return(returnValueLable, c.Length == 0 ? Expression.New(type) : Expression.New(type.GetConstructors()[0], ctorArgs)))); /* read.ReadLeftOrNull() return null if(_ReadBoolObjRight) reture new (default) int a; string b; i=2 while(i-->0) { var s= readString; ReadColon() switch(s) case(s=='Name') b=readValue case(s=='Age') a=readValue arrig=true if(!arrig) throw if(comma()) i++; } readRight(); return new dynamicModel(a,b) */ List args = new List() { }; if (c.Length > 0) { ParameterExpression str = Expression.Variable(typeof(string), "str"); LabelTarget whileBreak = Expression.Label(); methodCall.Add(ExpressionMembers.MoveNextAssignOne); LoopExpression loopExpression = Expression.Loop(Expression.IfThenElse(ExpressionMembers.MoveNextDecrement, ReturnFunc(() => { Expression[] expressions = new Expression[5]; expressions[0] = Expression.Assign(str, Expression.Call(ExpressionMembers.Reader, JsonReader._ReadString)); expressions[1] = Expression.Call(ExpressionMembers.Reader, JsonReader._ReadColon); expressions[2] = Expression.Switch(str, ReturnFunc(() => { SwitchCase[] switchCases = new SwitchCase[c.Length]; for (int i = 0; i < c.Length; i++) { switchCases[i] = Expression.SwitchCase( Expression.Block(typeof(void), Expression.Assign(ctorArgs[i], ExpressionMembers.GetMethodCall(c[i].PropertyType)), ExpressionMembers.IsArriveAssignTrue ) , Expression.Constant(c[i].Name, typeof(string))); } return switchCases; }) ); expressions[3] = Expression.IfThen(Expression.Equal(ExpressionMembers.IsArrive, Expression.Constant(false, typeof(bool))), Expression.Throw(Expression.New(JsonDeserializationTypeResolutionException._JsonDeserializationTypeResolutionExceptionMsgCtor, Expression.Constant("An error occurred parsing the dynamically typed key. The key does not match", typeof(string))))); expressions[4] = ExpressionMembers.IfReadBoolCommaIsTrueSoMoveNextIncrement; return Expression.Block(expressions); }), Expression.Break(whileBreak) )); methodCall.Add(loopExpression); methodCall.Add(Expression.Label(whileBreak)); args.Add(str); args.AddRange(ctorArgs); } methodCall.Add(Expression.Call(ExpressionMembers.Reader, JsonReader._ReadObjRight)); methodCall.Add(Expression.Return(returnValueLable, c.Length == 0 ? Expression.New(type) : Expression.New(type.GetConstructors()[0], ctorArgs))); methodCall.Add(Expression.Label(returnValueLable, Expression.Constant(null, type))); args.Add(ExpressionMembers.IsArrive); args.Add(ExpressionMembers.MoveNext); return Expression.Block(args, methodCall); } } }