2023-11-21 23:05:03 +08:00

110 lines
5.4 KiB
C#

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<Expression> methodCall = new List<Expression>();
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<ParameterExpression> args = new List<ParameterExpression>() { };
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>(() =>
{
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);
}
}
}