CPF/CPF.Windows/Json/Formatter/Serializer/Expression/IDictionaryGenericBuild.cs
2023-11-21 23:05:03 +08:00

72 lines
3.1 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq.Expressions;
namespace CPF.Windows.Json.Serializer
{
[ExpressionBuildType(SerializerBuildTypeEnum.IDictionaryGeneric)]
internal class IDictionaryGenericBuild : ExpressionJsonFormatter
{
internal static Expression Build(Type type, ParameterExpression instanceArg)
{
Type[] genericArguments = type.GetGenericArguments();
if (genericArguments.Length == 0)
{
Type idic = type.GetInterface("IDictionary`2");
genericArguments = idic.GetGenericArguments();
}
Type keyType = genericArguments[0];
Type valueType = genericArguments[1];
List<Expression> methodCall = new List<Expression>();
if (!type.IsValueType)
{
ConditionalExpression ifNullAppendNull = Expression.IfThen(
Expression.Equal(instanceArg, Expression.Constant(null, type)),
Expression.Block(ExpressionMembers.Append("null"),
Expression.Return(ExpressionMembers.ReturnLable)
));
methodCall.Add(ifNullAppendNull);
}
methodCall.Add(ExpressionMembers.IsIgnoreSelfRefernce(instanceArg, ExpressionMembers.RefernceByEmptyType.Dictionary));
methodCall.Add(ExpressionMembers.Append("{"));
ParameterExpression isFirst = Expression.Variable(typeof(bool), "isFirst");
Expression foreachs = ExpressionHelper.ForEach(instanceArg, Expression.Parameter(typeof(KeyValuePair<,>).MakeGenericType(keyType, valueType), "loopVar"),
item =>
{
List<Expression> calls = new List<Expression>
{
Expression.IfThenElse(
Expression.IsFalse(isFirst),
Expression.Assign(isFirst, Expression.Constant(true)),
ExpressionMembers.Append(",")
)
};
MemberExpression key = Expression.MakeMemberAccess(item, typeof(KeyValuePair<,>).MakeGenericType(keyType, valueType).GetProperty("Key"));
MemberExpression value = Expression.MakeMemberAccess(item, typeof(KeyValuePair<,>).MakeGenericType(keyType, valueType).GetProperty("Value"));
calls.Add(ExpressionMembers.WriteKeyValuePairKey(keyType, key));
calls.Add(ExpressionMembers.GetMethodCall(valueType, value));
return Expression.Block(new[] { isFirst }, calls);
}
);
methodCall.Add(foreachs);
methodCall.Add(ExpressionMembers.Append("}"));
methodCall.Add(ExpressionMembers.IsReferenceLoopHandlingIsNoneSerializeStacksArgPop);
methodCall.Add(Expression.Label(ExpressionMembers.ReturnLable));
return Expression.Block(methodCall);
}
}
}