internal SerializerOptions GetLeafSerializerOptions(ChainNode node) { var theDictionary = GetDictionary(node); var serializationType = Nullable.GetUnderlyingType(node.Type) ?? node.Type; if (!theDictionary.TryGetValue(serializationType, out SerializerOptions rule)) { var @delegate = CreateGeneralSerializer(serializationType, useToString); rule = new SerializerOptions(@delegate, nullSerializer, handleNullProperty, internalNodeOptions); } if (rule?.Serializer == null) { throw new NotConfiguredException($"Node '{node.FindLinkedRootXPath()}' included as leaf but serializer for its type '{serializationType.FullName}' is not configured"); } return(rule); }
public static Func <StringBuilder, T, bool> ComposeSerializer <T>( ChainNode root , Func <ChainNode, SerializerOptions> getSerializerOptions , Func <ChainNode, InternalNodeOptions> getInternalNodeOptions , bool rootHandleNull , bool rootHandleEmptyLiteral , Func <LambdaExpression, Delegate> compile , bool doCompileInnerLambdas ) { Func <StringBuilder, T, bool> @value = null; Expression serializeExpression; var objectType = typeof(T); var sbParameterExpression = Expression.Parameter(typeof(StringBuilder), "sb"); var tParameterExpression = Expression.Parameter(objectType, "t"); if (root.Children.Count == 0) // leaf { var serializerSet = getSerializerOptions(root); var isNullableStruct = JsonChainTools.IsNullableStruct(root.Type); if (isNullableStruct != null && isNullableStruct.Value == false) { var delegateMethodInfo = serializerSet.Serializer.GetMethodInfo(); var target = serializerSet.Serializer.Target; serializeExpression = Expression.Call(target != null ? Expression.Constant(target) : null, delegateMethodInfo, new Expression[] { sbParameterExpression, tParameterExpression }); } else { Expression nullCallExpression; if (rootHandleNull) { if (serializerSet.NullSerializer == null) { throw new NotSupportedException($"Null serializer is not setuped for root node"); } var rootNullSerializeMethodInfo = serializerSet.NullSerializer.GetMethodInfo(); nullCallExpression = Expression.Call(rootNullSerializeMethodInfo, new Expression[] { sbParameterExpression }); } else { nullCallExpression = Expression.Constant(false); } if (isNullableStruct == null) // class { var @delegate = serializerSet.Serializer.GetMethodInfo(); var methodCallExpression = Expression.Call(@delegate, new Expression[] { sbParameterExpression, tParameterExpression }); serializeExpression = Expression.Condition( Expression.Equal(tParameterExpression, Expression.Constant(null)), nullCallExpression, methodCallExpression ); } else if (isNullableStruct.Value) { var @delegate = serializerSet.Serializer.GetMethodInfo(); var hasValueExpression = Expression.Property(tParameterExpression, "HasValue"); var valueExpression = Expression.Property(tParameterExpression, "Value"); var methodCallExpression = Expression.Call(@delegate, new Expression[] { sbParameterExpression, valueExpression }); serializeExpression = Expression.Condition( hasValueExpression, methodCallExpression, nullCallExpression ); } else { throw new NotSupportedException(); } } } else // internal (note: currently can't be nullable struct) { var serializerSet = getInternalNodeOptions(root); var parentObjectAsArray = serializerSet.ObjectAsArray; var properies = new List <Expression>(); foreach (var c in root.Children) { var n = c.Value; JsonChainTools.ConfigureSerializeProperty(n, root.Type, parentObjectAsArray, properies, getSerializerOptions, getInternalNodeOptions, compile, doCompileInnerLambdas); } var methodCallExpression = JsonChainTools.CreateSerializeMethodCallExpression(sbParameterExpression, tParameterExpression, objectType, parentObjectAsArray, rootHandleEmptyLiteral, properies.ToArray()); if (JsonChainTools.IsNullable(root.Type)) { if (rootHandleNull) { if (serializerSet.NullSerializer == null) { throw new NotSupportedException($"Null serializer is not setuped for internal node '{root.FindLinkedRootXPath()}' "); } var rootNullSerializeMethodInfo = serializerSet.NullSerializer.GetMethodInfo(); MethodCallExpression nullCallExpression = Expression.Call(rootNullSerializeMethodInfo, new Expression[] { sbParameterExpression }); serializeExpression = Expression.Condition( Expression.Equal(tParameterExpression, Expression.Constant(null)), nullCallExpression, methodCallExpression ); } else { serializeExpression = Expression.Condition( Expression.Equal(tParameterExpression, Expression.Constant(null)), Expression.Constant(false), methodCallExpression ); } } else // struct { serializeExpression = methodCallExpression; } } var serializeLambda = Expression.Lambda(serializeExpression, new[] { sbParameterExpression, tParameterExpression }); @value = (Func <StringBuilder, T, bool>)compile(serializeLambda); return(@value); }