184 lines
10 KiB
C#
184 lines
10 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq.Expressions;
|
|
using System.Reflection;
|
|
using System.Text;
|
|
|
|
namespace CPF.Windows.Json.Serializer
|
|
{
|
|
[ExpressionBuildType(SerializerBuildTypeEnum.KeyValueObject)]
|
|
internal class KeyValueObjectBuild : ExpressionJsonFormatter
|
|
{
|
|
internal static Expression Build(Type type, ParameterExpression instanceArg)
|
|
{
|
|
List<Expression> methodCall = new List<Expression>();
|
|
|
|
if (!type.IsValueType)
|
|
{
|
|
ConditionalExpression ifParaIsNullAppendNull = Expression.IfThen(Expression.Equal(instanceArg, Expression.Constant(null, type)),
|
|
Expression.Block(
|
|
ExpressionMembers.Append("null"),
|
|
Expression.Return(ExpressionMembers.ReturnLable)
|
|
));
|
|
methodCall.Add(ifParaIsNullAppendNull);//add
|
|
|
|
Expression isIgnoreSelfRefernceModule = ExpressionMembers.IsIgnoreSelfRefernce(instanceArg, ExpressionMembers.RefernceByEmptyType.CustomType);
|
|
|
|
methodCall.Add(isIgnoreSelfRefernceModule);//add
|
|
}
|
|
|
|
methodCall.Add(ExpressionMembers.WriteLeft);
|
|
|
|
var elements = type.GetModelMembers(ReadMemberStateEnum.CanRead);
|
|
bool hasIgnoreDefaultValueAttribute = false;
|
|
for (int i = 0; i < elements.Count; i++)
|
|
{
|
|
var item = elements[i];
|
|
|
|
//valueformat
|
|
ValueFormatAttribute valueformat = item.Value.MemberInfo.GetCustomAttribute<ValueFormatAttribute>() ??
|
|
item.Value.MemberInfo.DeclaringType.GetCustomAttribute<ValueFormatAttribute>();
|
|
|
|
//IgnoreDefaultValue
|
|
IgnoreDefaultValueAttribute ignoreDefaultValue = item.Value.MemberInfo.GetCustomAttribute<IgnoreDefaultValueAttribute>() ??
|
|
item.Value.MemberInfo.DeclaringType.GetCustomAttribute<IgnoreDefaultValueAttribute>();
|
|
|
|
if (ignoreDefaultValue != null)
|
|
hasIgnoreDefaultValueAttribute = true;
|
|
|
|
//if (!(m.Name == null && handler.option.IsIgnoreNull))//0
|
|
MemberExpression mName = Expression.MakeMemberAccess(instanceArg, item.Value.MemberInfo);
|
|
|
|
// if (option1.IsFirstLower)
|
|
string lowerName = item.Key.Substring(0, 1).ToLower() + item.Key.Substring(1);
|
|
string upperName = item.Key.Substring(0, 1).ToUpper() + item.Key.Substring(1);
|
|
|
|
/*
|
|
ignoreKeys == null || ignoreKeys.count() == 0 || ignoreKeys.Contains(name)==false
|
|
*/
|
|
BinaryExpression ignoreKeysJudge = Expression.OrElse(
|
|
ExpressionMembers.IgnoreKeysIsNull,
|
|
Expression.OrElse(
|
|
ExpressionMembers.IgnoreKeysCountIsZero,
|
|
Expression.Equal(
|
|
Expression.Call(ExpressionMembers.IgnoreKeys, typeof(List<string>).GetMethod("Contains"), Expression.Constant(item.Key))
|
|
, Expression.Constant(false))
|
|
));
|
|
|
|
/*
|
|
(ignoreKeys == null || ignoreKeys.count() == 0 || ignoreKeys.Contains(name)==false) && ( m!=default(m) )
|
|
*/
|
|
if (ignoreDefaultValue != null)
|
|
ignoreKeysJudge = Expression.AndAlso(ignoreKeysJudge, Expression.NotEqual(mName, Expression.Constant(item.Value.Type.GetDefaultValue(), item.Value.Type)));
|
|
|
|
/*
|
|
if(option.keyformat!=null)
|
|
$handler.WriteString("\"");
|
|
$handler.WriteString(option.keyformat.invoke(string));
|
|
append("\":")
|
|
else
|
|
{
|
|
switch(JsonCharacterRead)
|
|
{
|
|
case None:
|
|
AppendKey()
|
|
case InitialUpper:
|
|
..
|
|
case InitialLower:
|
|
..
|
|
}
|
|
}
|
|
};
|
|
|
|
*/
|
|
Expression writeKey = Expression.IfThenElse(Expression.NotEqual(ExpressionMembers.GlobalKeyFormat, Expression.Constant(null, JsonSerializerOption._GlobalKeyFormat.FieldType)),
|
|
Expression.Block(
|
|
ExpressionMembers.Append("\""),
|
|
Expression.Call(ExpressionMembers.WriteString, JsonSerializerHandler._WriteStringInvoke, Expression.Call(ExpressionMembers.GlobalKeyFormat, JsonSerializerOption._GlobalKeyFormatInvoke, Expression.Constant(item.Key), Expression.Constant(type, typeof(Type)), ExpressionMembers.HandlerArg)
|
|
),
|
|
ExpressionMembers.Append("\":")
|
|
),
|
|
Expression.Switch(typeof(void), ExpressionMembers.JsonCharacterRead, null, null,
|
|
Expression.SwitchCase(ExpressionMembers.AppendKey(item.Key), Expression.Constant(JsonCharacterReadStateEnum.None, typeof(JsonCharacterReadStateEnum))),
|
|
Expression.SwitchCase(ExpressionMembers.AppendKey(upperName), Expression.Constant(JsonCharacterReadStateEnum.InitialUpper, typeof(JsonCharacterReadStateEnum))),
|
|
Expression.SwitchCase(ExpressionMembers.AppendKey(lowerName), Expression.Constant(JsonCharacterReadStateEnum.InitialLower, typeof(JsonCharacterReadStateEnum)))
|
|
)
|
|
);
|
|
|
|
|
|
/*
|
|
string afterValueFormat= valueformat.WriteValueFormat( model.Name,hander out isValueFormat)
|
|
if(isValueFormat)
|
|
sb.append(afterValueFormat)
|
|
else
|
|
WriteValue(model.Name,handler)
|
|
*/
|
|
Expression writeValue;
|
|
if (valueformat != null)
|
|
{
|
|
writeValue = Expression.Block(
|
|
Expression.NotEqual(ExpressionMembers.GlobalValueFormat, Expression.Constant(null, JsonSerializerOption._GlobalValueFormat.FieldType)),
|
|
Expression.Assign(ExpressionMembers.AfterValueFormat, Expression.Call(Expression.Constant(valueformat, typeof(ValueFormatAttribute)), ValueFormatAttribute._WriteValueFormat, Expression.Convert(mName, typeof(object)), Expression.Constant(item.Value.Type, typeof(Type)), ExpressionMembers.HandlerArg, ExpressionMembers.IsValueFormat)),
|
|
Expression.IfThenElse(Expression.IsTrue(ExpressionMembers.IsValueFormat), ExpressionMembers.Append(ExpressionMembers.AfterValueFormat), ExpressionMembers.GetMethodCall(item.Value.Type, mName))
|
|
);
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
if( option.GlobalValueFormat!=null){
|
|
string afterValueFormat= option.GlobalValueFormat.Invoke( model.Name,hander out isValueFormat)
|
|
if(isValueFormat)
|
|
sb.append(afterValueFormat)
|
|
else
|
|
WriteValue(model.Name,handler)
|
|
}
|
|
else
|
|
{
|
|
WriteValue(model.Name,handler)
|
|
}
|
|
*/
|
|
writeValue = Expression.IfThenElse(
|
|
Expression.NotEqual(ExpressionMembers.GlobalValueFormat, Expression.Constant(null, JsonSerializerOption._GlobalValueFormat.FieldType)),
|
|
Expression.Block(
|
|
Expression.Assign(ExpressionMembers.AfterValueFormat, Expression.Call(ExpressionMembers.GlobalValueFormat, JsonSerializerOption._GlobalValueFormatInvoke, Expression.Convert(mName, typeof(object)), Expression.Constant(item.Value.Type, typeof(Type)), ExpressionMembers.HandlerArg, ExpressionMembers.IsValueFormat)),
|
|
Expression.IfThenElse(Expression.IsTrue(ExpressionMembers.IsValueFormat), ExpressionMembers.Append(ExpressionMembers.AfterValueFormat), ExpressionMembers.GetMethodCall(item.Value.Type, mName))
|
|
),
|
|
ExpressionMembers.GetMethodCall(item.Value.Type, mName)
|
|
);
|
|
}
|
|
|
|
Expression trunk = Expression.Block(writeKey, writeValue);
|
|
|
|
// json.Append(",");
|
|
if (i != elements.Count - 1)
|
|
trunk = Expression.Block(trunk, ExpressionMembers.WriteComma);
|
|
|
|
if (!item.Value.Type.IsValueType || (item.Value.Type.IsGenericType && item.Value.Type.GetGenericTypeDefinition() == typeof(Nullable<>)))
|
|
{
|
|
BinaryExpression mNameIsNull = Expression.Equal(mName, Expression.Constant(null));
|
|
//if(!null&&isgorenull)
|
|
trunk = Expression.IfThen(Expression.IsFalse(Expression.And(mNameIsNull, ExpressionMembers.IgnoreValueNullIsTrue)), trunk);
|
|
}
|
|
//
|
|
trunk = Expression.IfThen(ignoreKeysJudge, trunk);//忽略key
|
|
|
|
methodCall.Add(trunk);
|
|
|
|
}
|
|
|
|
// //if ( ignoreValueNull == true || ignoreKeys!=null ) ==> RemoveLastComma()
|
|
var IgnoreValueNullIsTrueOrIgnoreKeysNotEqureNullRemoveLastComma = Expression.IfThen(
|
|
Expression.OrElse(ExpressionMembers.IgnoreValueNullIsTrue, ExpressionMembers.IgnoreKeysIsNotNull),
|
|
ExpressionMembers.RemoveLastComma()
|
|
);
|
|
methodCall.Add(hasIgnoreDefaultValueAttribute? (Expression)ExpressionMembers.RemoveLastComma():IgnoreValueNullIsTrueOrIgnoreKeysNotEqureNullRemoveLastComma);
|
|
methodCall.Add(ExpressionMembers.IsReferenceLoopHandlingIsRemoveDeleteComma);
|
|
methodCall.Add(ExpressionMembers.WriteRight);
|
|
methodCall.Add(ExpressionMembers.IsReferenceLoopHandlingIsNoneSerializeStacksArgPop);
|
|
methodCall.Add(Expression.Label(ExpressionMembers.ReturnLable));
|
|
|
|
return Expression.Block(new[] { ExpressionMembers.AfterValueFormat, ExpressionMembers.IsValueFormat }, methodCall);
|
|
}
|
|
}
|
|
}
|