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