示例#1
0
        private static Expression SerializeDictionaryWithDefaultComparer(Type genericDictionaryType,
                                                                         List <ParameterExpression> variables,
                                                                         Type type,
                                                                         ParameterExpression outputStream,
                                                                         ParameterExpression objToSerialize,
                                                                         ParameterExpression objTracking)
        {
            List <Expression> notTrackedExpressions = new List <Expression>();

            notTrackedExpressions.Add(PrimitiveHelpers.WriteByte(outputStream, Expression.Constant(SerializerObjectTracker.Value0, typeof(byte)), objTracking));

            var fields = InternalSerializationStuff.GetFields(type, genericDictionaryType);

            Serializer.GenerateFieldsExpression(type,
                                                fields,
                                                outputStream,
                                                objToSerialize,
                                                objTracking,
                                                variables,
                                                notTrackedExpressions);

            notTrackedExpressions.Add(SerializeDictionary(type,
                                                          genericDictionaryType,
                                                          variables,
                                                          outputStream,
                                                          objToSerialize,
                                                          objTracking,
                                                          false));

            return(Expression.Block(notTrackedExpressions));
        }
示例#2
0
        /// <summary>
        /// Generate an expression tree to clone a class
        /// </summary>
        /// <param name="variables">Global variables for the expression tree</param>
        /// <param name="sourceType">Type of the source object</param>
        /// <param name="source">Source object</param>
        /// <param name="clone">Clone object</param>
        /// <param name="refTrackerParam">Reference tracker</param>
        /// <returns>An expression tree that can clone a class</returns>
        internal static Expression GenerateClassExpressions(List <ParameterExpression> variables,
                                                            Type sourceType,
                                                            ParameterExpression source,
                                                            ParameterExpression clone,
                                                            ParameterExpression refTrackerParam)
        {
            var cloner     = Expression.Parameter(typeof(Func <object, ObjectClonerReferenceTracker, object>), "cloner");
            var clonedItem = Expression.Parameter(typeof(object), "clonedItem");

            variables.Add(cloner);
            variables.Add(clonedItem);

            var ctor = Expression.Call(FormatterServicesMih.GetUninitializedObject(), Expression.Constant(sourceType));

            var copyExpressions = new List <Expression>();
            var fields          = InternalSerializationStuff.GetFields(sourceType);

            copyExpressions.Add(Expression.Assign(clone, Expression.Convert(ctor, sourceType)));
            copyExpressions.Add(Expression.Call(refTrackerParam, ObjectClonerReferenceTrackerMih.Track(), source, clone));
            GenerateCopyFieldsExpressions(fields,
                                          source,
                                          clone,
                                          copyExpressions,
                                          refTrackerParam,
                                          clonedItem);

            return(ObjectCloner.GenerateNullTrackedOrUntrackedExpression(source,
                                                                         clone,
                                                                         sourceType,
                                                                         refTrackerParam,
                                                                         Expression.Block(copyExpressions)));
        }
示例#3
0
        private static Expression GenerateClassExpression(Type type,
                                                          ParameterExpression inputStream,
                                                          ParameterExpression objTracker)
        {
            List <ParameterExpression> variables = new List <ParameterExpression>();

            var trackType    = Expression.Parameter(typeof(byte), "isAlreadyTracked");
            var newInstance  = Expression.Parameter(type, "newInstance");
            var deserializer = Expression.Parameter(typeof(Func <Stream, DeserializerObjectTracker, object>), "deserializer");
            var typeExpr     = Expression.Parameter(typeof(TypeWithHashCode), "typeExpr");
            var typeName     = Expression.Parameter(typeof(string), "typeName");
            var typeHashCode = Expression.Parameter(typeof(int), "typeHashCode");

            variables.Add(trackType);
            variables.Add(newInstance);
            variables.Add(deserializer);
            variables.Add(typeExpr);
            variables.Add(typeName);
            variables.Add(typeHashCode);
            var temporaryVariables = new Dictionary <Type, ParameterExpression>();

            List <Expression> notTrackedExpressions = new List <Expression>();

            notTrackedExpressions.Add(Expression.Assign(newInstance, Expression.Convert(Expression.Call(FormatterServicesMih.GetUninitializedObject(), Expression.Constant(type)), type)));
            notTrackedExpressions.AddRange(SerializationCallbacksHelper.GenerateOnDeserializingAttributeExpression(type, newInstance, Expression.New(StreamingContextMih.Constructor(), Expression.Constant(StreamingContextStates.All))));

            if (type.IsClass)
            {
                notTrackedExpressions.Add(Expression.Call(objTracker, DeserializerObjectTrackerMih.TrackedObject(), newInstance));
            }

            GenerateReadFieldsExpression(type,
                                         InternalSerializationStuff.GetFields(type),
                                         inputStream,
                                         objTracker,
                                         temporaryVariables,
                                         variables,
                                         newInstance,
                                         notTrackedExpressions,
                                         typeExpr,
                                         typeName,
                                         typeHashCode,
                                         deserializer);

            notTrackedExpressions.AddRange(SerializationCallbacksHelper.GenerateOnDeserializedAttributeExpression(type, newInstance, Expression.New(StreamingContextMih.Constructor(), Expression.Constant(StreamingContextStates.All))));
            notTrackedExpressions.Add(SerializationCallbacksHelper.GenerateCallIDeserializationExpression(type, newInstance));

            return(Deserializer.GenerateNullTrackedOrUntrackedExpression(type,
                                                                         inputStream,
                                                                         objTracker,
                                                                         newInstance,
                                                                         notTrackedExpressions,
                                                                         trackType,
                                                                         variables));
        }
示例#4
0
        private static Func <object, ObjectClonerReferenceTracker, object> GenerateCloner(Type sourceType)
        {
            InternalSerializationStuff.ValidateSupportedTypes(sourceType);

            ParameterExpression sourceParameter = Expression.Parameter(typeof(object), "sourceParam");
            ParameterExpression refTrackerParam = Expression.Parameter(typeof(ObjectClonerReferenceTracker), "refTrackerParam");

            var clone  = Expression.Parameter(sourceType, "newInstance");
            var source = Expression.Parameter(sourceType, "source");

            var variables   = new List <ParameterExpression>();
            var expressions = new List <Expression>();

            variables.Add(source);
            variables.Add(clone);
            expressions.Add(Expression.Assign(source, Expression.Convert(sourceParameter, sourceType)));

            if (sourceType.IsPrimitive || sourceType.IsValueType || (sourceType == typeof(string)))
            {
                expressions.Add(Expression.Assign(clone, source));
            }
            else if (InternalSerializationStuff.ImplementsISerializableWithSerializationConstructor(sourceType))
            {
                expressions.Add(ISerializableCloner.GenerateISerializableExpression(variables, source, clone, sourceType, refTrackerParam));
            }
            else if (InternalSerializationStuff.ImplementsDictionaryGeneric(sourceType))
            {
                expressions.Add(DictionaryCloner.GenerateDictionaryGenericExpression(variables, source, clone, sourceType, refTrackerParam));
            }
            else if (sourceType == typeof(ExpandoObject))
            {
                expressions.Add(ExpandoCloner.GenerateExpandoObjectExpression(variables, source, clone, refTrackerParam));
            }
            else if (sourceType.IsArray)
            {
                expressions.Add(ArrayCloner.GenerateArrayExpression(variables, source, clone, sourceType, refTrackerParam));
            }
            else
            {
                expressions.Add(ClassCloner.GenerateClassExpressions(variables, sourceType, source, clone, refTrackerParam));
            }

            // Value types require manual boxing
            if (sourceType.IsValueType)
            {
                expressions.Add(Expression.Convert(clone, typeof(object)));
            }
            else
            {
                expressions.Add(clone);
            }

            return(Expression.Lambda <Func <object, ObjectClonerReferenceTracker, object> >(Expression.Block(variables, expressions), sourceParameter, refTrackerParam).Compile());
        }
        public void GetFieldShouldExcludeSpecifiedBaseClass()
        {
            var fields = InternalSerializationStuff.GetFields(typeof(CustomDictionaryWithAdditionalPropertiesWithoutOverridingOnDeserializedCallback),
                                                              typeof(Dictionary <string, object>));

            fields.Select(x => x.Name)
            .ToArray()
            .Should()
            .BeEquivalentTo(new[]
            {
                "<SomeProperty>k__BackingField"
            });
        }
示例#6
0
        private static Expression SerializeDictionaryWithCustomComparer(Type genericDictionaryType,
                                                                        List <ParameterExpression> variables,
                                                                        Type type,
                                                                        ParameterExpression outputStream,
                                                                        ParameterExpression objToSerialize,
                                                                        ParameterExpression objTracking)
        {
            var serializer = Expression.Parameter(typeof(Action <Stream, object, SerializerObjectTracker>), "serializer");
            var typeExpr   = Expression.Parameter(typeof(Type), "typeExpr");
            var itemAsObj  = Expression.Parameter(typeof(object), "itemAsObj");

            variables.Add(serializer);
            variables.Add(typeExpr);
            variables.Add(itemAsObj);

            List <Expression> notTrackedExpressions = new List <Expression>();

            notTrackedExpressions.Add(PrimitiveHelpers.WriteByte(outputStream, Expression.Constant(SerializerObjectTracker.Value1, typeof(byte)), objTracking));

            var comparerProperty = Expression.Property(objToSerialize, nameof(Dictionary <int, int> .Comparer));

            notTrackedExpressions.Add(Serializer.GetWriteClassTypeExpression(outputStream,
                                                                             objTracking,
                                                                             comparerProperty,
                                                                             itemAsObj,
                                                                             typeExpr,
                                                                             serializer,
                                                                             typeof(object)));

            var fields = InternalSerializationStuff.GetFields(type, genericDictionaryType);

            Serializer.GenerateFieldsExpression(type,
                                                fields,
                                                outputStream,
                                                objToSerialize,
                                                objTracking,
                                                variables,
                                                notTrackedExpressions);

            notTrackedExpressions.Add(SerializeDictionary(type,
                                                          genericDictionaryType,
                                                          variables,
                                                          outputStream,
                                                          objToSerialize,
                                                          objTracking,
                                                          false));

            return(Expression.Block(notTrackedExpressions));
        }
示例#7
0
        private static System.Delegate CreateTypeSerializer(Type type)
        {
            InternalSerializationStuff.ValidateSupportedTypes(type);

            var variables      = new List <ParameterExpression>();
            var expressions    = new List <Expression>();
            var outputStream   = Expression.Parameter(typeof(Stream), "outputStream");
            var objToSerialize = Expression.Parameter(type, "objToSerialize");
            var objTracking    = Expression.Parameter(typeof(SerializerObjectTracker), "objTracking");

            var primitiveWriter = GetPrimitiveWriter(type);

            if (primitiveWriter != null)
            {
                Debug.Assert(type.IsPrimitive || type.IsValueType, "Value is not a primitive");
                expressions.Add(primitiveWriter(outputStream, objToSerialize, objTracking));
            }
            else if (type == typeof(string))
            {
                expressions.Add(GenerateStringExpression(outputStream, objToSerialize, objTracking));
            }
            else if (InternalSerializationStuff.ImplementsISerializableWithSerializationConstructor(type))
            {
                expressions.Add(ISerializableSerializer.GenerateISerializableExpression(type, variables, outputStream, objToSerialize, objTracking));
            }
            else if (InternalSerializationStuff.ImplementsDictionaryGeneric(type))
            {
                expressions.Add(DictionarySerializer.GenerateDictionaryGenericExpression(type, variables, outputStream, objToSerialize, objTracking));
            }
            else if (type == typeof(ExpandoObject))
            {
                expressions.Add(ExpandoSerializer.GenerateExpandoObjectExpression(type, variables, outputStream, objToSerialize, objTracking));
            }
            else if (type.IsArray)
            {
                expressions.Add(GenerateArrayExpression(type, outputStream, objToSerialize, objTracking));
            }
            else
            {
                expressions.Add(GenerateClassExpression(type, outputStream, objToSerialize, objTracking));
            }

            var block = Expression.Block(variables, expressions);

            var a = typeof(Action <, ,>).MakeGenericType(typeof(Stream), type, typeof(SerializerObjectTracker));

            return(Expression.Lambda(a, block, outputStream, objToSerialize, objTracking).Compile());
        }
示例#8
0
        private static System.Delegate CreateTypeDeserializer(Type type)
        {
            var expressions = new List <Expression>();
            var variables   = new List <ParameterExpression>();
            var inputStream = Expression.Parameter(typeof(Stream), "inputStream");
            var objTracker  = Expression.Parameter(typeof(DeserializerObjectTracker), "objTracker");
            var returnValue = Expression.Parameter(type, "retVal");

            variables.Add(returnValue);

            var primitiveReader = GetPrimitiveReader(type);

            if (primitiveReader != null)
            {
                expressions.Add(Expression.Assign(returnValue, Expression.Convert(primitiveReader(inputStream, objTracker), type)));
            }
            else if (type == typeof(string))
            {
                expressions.Add(Expression.Assign(returnValue, GenerateStringExpression(inputStream, objTracker)));
            }
            else if (InternalSerializationStuff.ImplementsISerializableWithSerializationConstructor(type))
            {
                expressions.Add(Expression.Assign(returnValue, ISerializableDeserializer.GenerateISerializableExpression(type, variables, inputStream, objTracker)));
            }
            else if (InternalSerializationStuff.ImplementsDictionaryGeneric(type))
            {
                expressions.Add(Expression.Assign(returnValue, DictionaryDeserializer.GenerateDictionaryGenericExpression(type, variables, inputStream, objTracker)));
            }
            else if (type.IsArray)
            {
                expressions.Add(Expression.Assign(returnValue, GenerateArrayExpression(type, inputStream, objTracker)));
            }
            else if (type == typeof(ExpandoObject))
            {
                expressions.Add(Expression.Assign(returnValue, ExpandoDeserializer.GenerateExpandoObjectExpression(variables, inputStream, objTracker)));
            }
            else
            {
                expressions.Add(Expression.Assign(returnValue, GenerateClassExpression(type, inputStream, objTracker)));
            }

            expressions.Add(returnValue);

            var block = Expression.Block(variables, expressions);
            var f     = typeof(Func <, ,>).MakeGenericType(typeof(Stream), typeof(DeserializerObjectTracker), type);

            return(Expression.Lambda(f, block, inputStream, objTracker).Compile());
        }
示例#9
0
        private static Expression DeserializeDictionary(Type type,
                                                        Type genericDictionaryType,
                                                        List <ParameterExpression> variables,
                                                        ParameterExpression newInstance,
                                                        ParameterExpression inputStream,
                                                        ParameterExpression objTracker,
                                                        ParameterExpression deserializer,
                                                        ParameterExpression typeExpr,
                                                        ParameterExpression typeName,
                                                        ParameterExpression typeHashCode,
                                                        Action <List <Expression>, ParameterExpression> createClassAction)
        {
            var expressions = new List <Expression>();

            var trackType = Expression.Parameter(typeof(byte), "isAlreadyTracked");

            variables.Add(trackType);
            var temporaryVariables = new Dictionary <Type, ParameterExpression>();

            var fields = InternalSerializationStuff.GetFields(type, genericDictionaryType);

            createClassAction(expressions, newInstance);
            expressions.Add(Expression.Call(objTracker, DeserializerObjectTrackerMih.TrackedObject(), newInstance));

            Deserializer.GenerateReadFieldsExpression(type,
                                                      fields,
                                                      inputStream,
                                                      objTracker,
                                                      temporaryVariables,
                                                      variables,
                                                      newInstance,
                                                      expressions,
                                                      typeExpr,
                                                      typeName,
                                                      typeHashCode,
                                                      deserializer);

            expressions.AddRange(DeserializeDictionaryValues(type, variables, inputStream, objTracker, newInstance));

            //expressions.AddRange(SerializationCallbacksHelper.GenerateOnDeserializedAttributeExpression(type, newInstance, Expression.New(StreamingContextMih.Constructor(), Expression.Constant(StreamingContextStates.All))));
            //expressions.Add(SerializationCallbacksHelper.GenerateCallIDeserializationExpression(type, newInstance));

            return(Expression.Block(expressions));
        }
        public void GetFieldsShouldIncludeBaseClass()
        {
            var fields = InternalSerializationStuff.GetFields(typeof(CustomDictionaryWithAdditionalPropertiesWithoutOverridingOnDeserializedCallback));

            fields.Select(x => x.Name)
            .ToArray()
            .Should()
            .BeEquivalentTo(new[]
            {
                "<SomeProperty>k__BackingField",
                "_syncRoot",
                "buckets",
                "comparer",
                "count",
                "entries",
                "freeCount",
                "freeList",
                "keys",
                "values",
                "version"
            });
        }
示例#11
0
        /// <summary>
        /// Generate an epxression tree to handle class serialization
        /// </summary>
        /// <param name="type">Type to serialize</param>
        /// <param name="outputStream">Stream to write to</param>
        /// <param name="objToSerialize">Object to serialize</param>
        /// <param name="objTracking">Reference tracker</param>
        /// <returns>An epxression tree to handle class serialization</returns>
        internal static Expression GenerateClassExpression(Type type,
                                                           ParameterExpression outputStream,
                                                           Expression objToSerialize,
                                                           ParameterExpression objTracking)
        {
            List <Expression>          notTrackedExpressions = new List <Expression>();
            List <ParameterExpression> variables             = new List <ParameterExpression>();

            GenerateFieldsExpression(type,
                                     InternalSerializationStuff.GetFields(type),
                                     outputStream,
                                     objToSerialize,
                                     objTracking,
                                     variables,
                                     notTrackedExpressions);

            return(GenerateNullTrackedOrUntrackedExpression(type,
                                                            outputStream,
                                                            objToSerialize,
                                                            objTracking,
                                                            notTrackedExpressions,
                                                            variables));
        }
示例#12
0
        private static void CopyFieldsAndValues(Type genericDictionaryType,
                                                ParameterExpression source,
                                                ParameterExpression clone,
                                                Type sourceType,
                                                ParameterExpression refTrackerParam,
                                                List <Expression> expressions,
                                                List <ParameterExpression> variables)
        {
            var clonedItem = Expression.Parameter(typeof(object), "clonedItem");

            variables.Add(clonedItem);

            var fields = InternalSerializationStuff.GetFields(sourceType,
                                                              genericDictionaryType);

            ClassCloner.GenerateCopyFieldsExpressions(fields,
                                                      source,
                                                      clone,
                                                      expressions,
                                                      refTrackerParam,
                                                      clonedItem);

            var typeKey   = genericDictionaryType.GenericTypeArguments[0];
            var typeValue = genericDictionaryType.GenericTypeArguments[1];

            if (IsPrimitive(typeKey) &&
                IsPrimitive(typeValue))
            {
                expressions.Add(Expression.Call(typeof(DictionaryCloner),
                                                nameof(DictionaryCloner.CopyPrimitiveKeyAndPrimitiveValue),
                                                genericDictionaryType.GenericTypeArguments,
                                                source,
                                                clone));
            }
            else if (!IsPrimitive(typeKey) &&
                     IsPrimitive(typeValue))
            {
                expressions.Add(Expression.Call(typeof(DictionaryCloner),
                                                nameof(DictionaryCloner.CopyObjectKeyAndPrimitiveValue),
                                                genericDictionaryType.GenericTypeArguments,
                                                source,
                                                clone,
                                                refTrackerParam));
            }
            else if (IsPrimitive(typeKey) &&
                     !IsPrimitive(typeValue))
            {
                expressions.Add(Expression.Call(typeof(DictionaryCloner),
                                                nameof(DictionaryCloner.CopyPrivitiveKeyAndObjectValue),
                                                genericDictionaryType.GenericTypeArguments,
                                                source,
                                                clone,
                                                refTrackerParam));
            }
            else
            {
                expressions.Add(Expression.Call(typeof(DictionaryCloner),
                                                nameof(DictionaryCloner.CopyObjectKeyAndObjectValue),
                                                genericDictionaryType.GenericTypeArguments,
                                                source,
                                                clone,
                                                refTrackerParam));
            }
        }