Exemplo n.º 1
0
        private dyn_serialize makeSerialize()
        {
            var _walkArrayWrite = typeof(TypeDescriptor).GetMethod("walkArrayWrite", BindingFlags.NonPublic | BindingFlags.Static);

            var pSchema           = Expression.Parameter(typeof(TypeSchema));
            var pWriter           = Expression.Parameter(typeof(SlimWriter));
            var pTReg             = Expression.Parameter(typeof(TypeRegistry));
            var pRefs             = Expression.Parameter(typeof(RefPool));
            var pInstance         = Expression.Parameter(typeof(object));
            var pStreamingContext = Expression.Parameter(typeof(StreamingContext));

            var expressions = new List <Expression>();

            var instance = Expression.Variable(Type, "instance");

            expressions.Add(Expression.Assign(instance, Expression.Convert(pInstance, Type)));


            if (IsPrimitive)
            {
                expressions.Add(Expression.Call(pWriter,
                                                Format.GetWriteMethodForType(Type),
                                                instance));
            }
            else if (IsArray)
            {
                var elmType = Type.GetElementType();

                if (Format.IsTypeSupported(elmType)) //array element type
                {                                    //spool whole array into writer using primitive types
                    var pElement = Expression.Parameter(typeof(object));
                    expressions.Add(Expression.Call(_walkArrayWrite,
                                                    instance,
                                                    Expression.Lambda(Expression.Call(pWriter,
                                                                                      Format.GetWriteMethodForType(elmType),
                                                                                      Expression.Convert(pElement, elmType)), pElement)
                                                    )
                                    );
                }
                else
                {   //spool whole array using TypeSchema because objects may change type
                    var pElement = Expression.Parameter(typeof(object));

                    if (!elmType.IsValueType)//reference type
                    {
                        expressions.Add(Expression.Call(_walkArrayWrite,
                                                        instance,
                                                        Expression.Lambda(Expression.Call(pSchema,
                                                                                          typeof(TypeSchema).GetMethod("writeRefMetaHandle"),
                                                                                          pWriter,
                                                                                          pTReg,
                                                                                          pRefs,
                                                                                          Expression.Convert(pElement, typeof(object)),
                                                                                          pStreamingContext),
                                                                          pElement)
                                                        )
                                        );
                    }
                    else
                    {
                        expressions.Add(Expression.Call(_walkArrayWrite,
                                                        instance,
                                                        Expression.Lambda(Expression.Call(pSchema,
                                                                                          typeof(TypeSchema).GetMethod("Serialize"),
                                                                                          pWriter,
                                                                                          pTReg,
                                                                                          pRefs,
                                                                                          pElement,
                                                                                          pStreamingContext,
                                                                                          Expression.Constant(elmType)//valueType
                                                                                          ), pElement)
                                                        )
                                        );
                    }
                }
            }
            else
            {
                foreach (var field in Fields)
                {
                    Expression expr = null;
                    Type       t    = field.FieldType;

                    if (Format.IsTypeSupported(t))
                    {
                        expr = Expression.Call(pWriter,
                                               Format.GetWriteMethodForType(t),
                                               Expression.Field(instance, field));
                    }

/* 20150316 DKh, introduction of Metahandle.InlinedTypeValue
 *                else
 *                if (t == typeof(Type))
 *                {
 *                  expr = Expression.IfThenElse(
 *                                Expression.Equal(Expression.Field(instance, field), Expression.Constant(null, typeof(Type))),
 *
 *                              //then
 *                                Expression.Call(pWriter,
 *                                         Format.GetWriteMethodForType(typeof(string)),
 *                                         Expression.Constant(null, typeof(string))),
 *                              //else
 *                                Expression.Call(pWriter,
 *                                         typeof(SlimWriter).GetMethod("Write", new Type[] {typeof(string)}),
 *                                         Expression.Call(pTReg,
 *                                                         typeof(TypeRegistry).GetMethod("GetTypeHandle"),
 *                                                         Expression.Field(instance, field)))
 *                  );//ifthenelse
 *                }
 */
                    else
                    if (t.IsEnum)
                    {
                        expr = Expression.Call(pWriter,
                                               Format.GetWriteMethodForType(typeof(int)),
                                               Expression.Convert(Expression.Field(instance, field), typeof(int)));
                    }
                    else // complex type ->  struct or reference
                    {
                        if (!t.IsValueType)//reference type -> write metahandle
                        {
                            expr = Expression.Call(pSchema,
                                                   typeof(TypeSchema).GetMethod("writeRefMetaHandle"),
                                                   pWriter,
                                                   pTReg,
                                                   pRefs,
                                                   Expression.Convert(Expression.Field(instance, field), typeof(object)),
                                                   pStreamingContext);
                        }
                        else
                        {
                            expr = Expression.Call(pSchema,
                                                   typeof(TypeSchema).GetMethod("Serialize"),
                                                   pWriter,
                                                   pTReg,
                                                   pRefs,
                                                   Expression.Convert(Expression.Field(instance, field), typeof(object)),
                                                   pStreamingContext,
                                                   Expression.Constant(field.FieldType));//valueType
                        }
                    }

                    expressions.Add(expr);
                }//foreach
            }

            var body = Expression.Block(new ParameterExpression[] { instance }, expressions);

            return(Expression.Lambda <dyn_serialize>(body, pSchema, pWriter, pTReg, pRefs, pInstance, pStreamingContext).Compile());
        }