Пример #1
0
        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);
        }
Пример #2
0
        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);
        }