예제 #1
0
        /// <summary>
        /// Generates an expression to handle the 'is that object null' case
        /// </summary>
        /// <param name="type">Type of <paramref name="objToSerialize"/></param>
        /// <param name="outputStream">Stream to write to</param>
        /// <param name="objToSerialize">Object to serialize</param>
        /// <param name="objTracking">Reference tracker</param>
        /// <param name="notTrackedExpressions">Expressions that must be executed if the object is not tracked</param>
        /// <param name="variables">Global variables for the expression tree</param>
        /// <returns>An expression to handle the 'is that object null' case</returns>
        internal static Expression GenerateNullTrackedOrUntrackedExpression(Type type,
                                                                            ParameterExpression outputStream,
                                                                            Expression objToSerialize,
                                                                            ParameterExpression objTracking,
                                                                            List <Expression> notTrackedExpressions,
                                                                            List <ParameterExpression> variables)
        {
            var trackedObjectPosition = Expression.Parameter(typeof(int?), "trackedObjectPosition");
            var canBeTracked          = Expression.Parameter(typeof(bool), "canBeTracked");

            variables.Add(trackedObjectPosition);
            variables.Add(canBeTracked);

            var alreadyTrackedExpr = Expression.Block(PrimitiveHelpers.WriteByte(outputStream, Expression.Constant(SerializerObjectTracker.Value0), objTracking),
                                                      PrimitiveHelpers.WriteInt32(outputStream, Expression.Convert(trackedObjectPosition, typeof(int)), objTracking));

            var isNullExpr = PrimitiveHelpers.WriteByte(outputStream, Expression.Constant(SerializerObjectTracker.Value0, typeof(byte)), objTracking);

            var isNotNullExpr = Expression.Block(PrimitiveHelpers.WriteByte(outputStream, Expression.Constant(SerializerObjectTracker.Value1), objTracking),
                                                 Expression.IfThenElse(Expression.IsTrue(canBeTracked),
                                                                       Expression.Assign(trackedObjectPosition, Expression.Call(objTracking, SerializerObjectTrackerMih.GetTrackedObjectIndex(), Expression.Convert(objToSerialize, typeof(object)))),
                                                                       Expression.Assign(trackedObjectPosition, Expression.Convert(Expression.Constant(null), typeof(int?)))),
                                                 Expression.IfThenElse(Expression.NotEqual(trackedObjectPosition, Expression.Constant(null, typeof(int?))),
                                                                       alreadyTrackedExpr,
                                                                       Expression.Block(new[] { PrimitiveHelpers.WriteByte(outputStream, Expression.Constant(SerializerObjectTracker.Value1), objTracking) }.Concat(notTrackedExpressions))));

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

            expressions.Add(Expression.Assign(canBeTracked, Expression.Call(objTracking, SerializerObjectTrackerMih.CanBeTracked(), Expression.Constant(type))));
            expressions.Add(Expression.IfThenElse(Expression.AndAlso(Expression.IsTrue(canBeTracked), Expression.Equal(Expression.Convert(objToSerialize, typeof(object)), Expression.Constant(null))),
                                                  isNullExpr,
                                                  isNotNullExpr));

            return(Expression.Block(variables, expressions));
        }
예제 #2
0
        /// <summary>
        /// Generate an expression tree to deserialize a class
        /// </summary>
        /// <param name="inputStream">Stream to read from</param>
        /// <param name="objTracker">Reference tracker</param>
        /// <param name="leftSide">Left side of the assignment</param>
        /// <param name="typeExpr">Type of the class as an expression</param>
        /// <param name="typeName">Type of the class as a string</param>
        /// <param name="typeHashCode">Hashcode of the class</param>
        /// <param name="deserializer">Temporary deserializer variable</param>
        /// <param name="itemType">Type of the class</param>
        /// <returns>An expression tree to deserialize a class</returns>
        internal static Expression GetReadClassExpression(ParameterExpression inputStream,
                                                          ParameterExpression objTracker,
                                                          Expression leftSide,
                                                          ParameterExpression typeExpr,
                                                          ParameterExpression typeName,
                                                          ParameterExpression typeHashCode,
                                                          ParameterExpression deserializer,
                                                          Type itemType)
        {
            var readType = Expression.IfThenElse(Expression.Equal(Expression.Convert(PrimitiveHelpers.ReadByte(inputStream, objTracker), typeof(byte)), Expression.Constant(SerializerObjectTracker.Value0)),
                                                 Expression.Assign(typeExpr, Expression.Call(SerializedTypeResolverMih.GetTypeFromFullName_Type(), Expression.Constant(itemType))),
                                                 Expression.Block(Expression.Assign(typeName, Deserializer.GenerateStringExpression(inputStream, objTracker)),
                                                                  Expression.Assign(typeHashCode, PrimitiveHelpers.ReadInt32(inputStream, objTracker)),
                                                                  Expression.Assign(typeExpr, Expression.Call(SerializedTypeResolverMih.GetTypeFromFullName_String(), typeName)),
                                                                  Expression.IfThen(Expression.NotEqual(typeHashCode, Expression.Property(typeExpr, "HashCode")),
                                                                                    Expression.Throw(Expression.New(TypeWasModifiedSinceSerializationException.GetConstructor(), typeExpr)))));

            var        invokeDeserializer = Expression.Invoke(deserializer, inputStream, objTracker);
            Expression convertExpression  = Expression.Convert(Expression.Call(SerializerMih.ConvertObjectToExpectedType(), invokeDeserializer, Expression.Constant(itemType)), itemType);

            return(Expression.IfThenElse(Expression.Equal(Expression.Convert(PrimitiveHelpers.ReadByte(inputStream, objTracker), typeof(byte)), Expression.Constant(SerializerObjectTracker.Value0)),
                                         Expression.Assign(leftSide, Expression.Constant(null, itemType)),
                                         Expression.Block(
                                             readType,
                                             Expression.Assign(deserializer, Expression.Call(DeserializerMih.GetTypeToObjectDeserializer(), Expression.Property(typeExpr, "Type"))),
                                             Expression.Assign(leftSide, convertExpression))));
        }
예제 #3
0
        private static IEnumerable <Expression> WriteDimensionalArrayLength(ParameterExpression outputStream,
                                                                            Expression objTracking,
                                                                            Expression i,
                                                                            ParameterExpression arr,
                                                                            ParameterExpression lengths,
                                                                            int rank)
        {
            var expressions = new List <Expression>();

            expressions.Add(PrimitiveHelpers.WriteByte(outputStream, Expression.Constant((byte)rank), objTracking));

            var loopExpressions = new List <Expression>();

            expressions.Add(Expression.Assign(i, Expression.Constant(0)));

            var length = Expression.Call(arr, ArrayMih.GetLength(), i);

            loopExpressions.Add(Expression.Assign(Expression.ArrayAccess(lengths, i), length));
            loopExpressions.Add(PrimitiveHelpers.WriteInt32(outputStream, Expression.ArrayIndex(lengths, i), objTracking));
            loopExpressions.Add(Expression.Assign(i, Expression.Add(i, Expression.Constant(1))));

            var loopBody   = Expression.Block(loopExpressions);
            var breakLabel = Expression.Label("breakLabel");
            var cond       = Expression.LessThan(i, Expression.Constant(rank));
            var loop       = Expression.Loop(Expression.IfThenElse(cond,
                                                                   loopBody,
                                                                   Expression.Break(breakLabel)),
                                             breakLabel);

            expressions.Add(loop);

            return(expressions);
        }
예제 #4
0
        /// <summary>
        /// Generates an expression tree to handle ISerializable deserialization
        /// </summary>
        /// <param name="type">Type to deserialize</param>
        /// <param name="variables">Global variables for expression tree</param>
        /// <param name="inputStream">Stream to read from</param>
        /// <param name="objTracker">Reference tracker</param>
        /// <returns>An expression tree to handle ISerializable deserialization</returns>
        public static Expression GenerateISerializableExpression(Type type,
                                                                 List <ParameterExpression> variables,
                                                                 ParameterExpression inputStream,
                                                                 ParameterExpression objTracker)
        {
            var newInstance = Expression.Parameter(type, "newInstance");
            var trackType   = Expression.Parameter(typeof(byte), "trackType");

            variables.Add(newInstance);
            variables.Add(trackType);

            var dictionaryType        = DictionaryHelper.GetDictionaryType(type, throwIfNotADictionary: false);
            var notTrackedExpressions = new List <Expression>();

            if (dictionaryType == null)
            {
                notTrackedExpressions.Add(PrimitiveHelpers.ReadByte(inputStream, objTracker));
                notTrackedExpressions.Add(DeserializeISerializable(type, variables, inputStream, objTracker, newInstance));
            }
            else
            {
                notTrackedExpressions.Add(Expression.IfThenElse(Expression.Equal(PrimitiveHelpers.ReadByte(inputStream, objTracker), Expression.Constant(1, typeof(int))),
                                                                DeserializeDictionary(type, variables, inputStream, objTracker, newInstance),
                                                                DeserializeISerializable(type, variables, inputStream, objTracker, newInstance)));
            }

            return(Deserializer.GenerateNullTrackedOrUntrackedExpression(type,
                                                                         inputStream,
                                                                         objTracker,
                                                                         newInstance,
                                                                         notTrackedExpressions,
                                                                         trackType,
                                                                         variables));
        }
예제 #5
0
        /// <summary>
        /// Generates an expression tree to read a string
        /// </summary>
        /// <param name="inputStream">Stream to read from</param>
        /// <param name="objTracking">Reference tracker</param>
        /// <returns>An expression tree to read a string</returns>
        internal static Expression GenerateStringExpression(ParameterExpression inputStream,
                                                            ParameterExpression objTracking)
        {
            List <ParameterExpression> variables = new List <ParameterExpression>();

            var trackType    = Expression.Parameter(typeof(byte), "isAlreadyTracked");
            var newInstance  = Expression.Parameter(typeof(string), "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);

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

            notTrackedExpressions.Add(Expression.Assign(newInstance, PrimitiveHelpers.ReadString(inputStream, objTracking)));
            notTrackedExpressions.Add(Expression.Call(objTracking, DeserializerObjectTrackerMih.TrackedObject(), newInstance));

            return(Deserializer.GenerateNullTrackedOrUntrackedExpression(typeof(string),
                                                                         inputStream,
                                                                         objTracking,
                                                                         newInstance,
                                                                         notTrackedExpressions,
                                                                         trackType,
                                                                         variables));
        }
예제 #6
0
        /// <summary>
        /// Generates an expression tree to handle ExpandoObject serialization
        /// </summary>
        /// <param name="type">Type of <paramref name="objToSerialize"/></param>
        /// <param name="variables">Global variables for the expression tree</param>
        /// <param name="outputStream">Stream to write to</param>
        /// <param name="objToSerialize">Object to serialize</param>
        /// <param name="objTracking">Reference tracker</param>
        /// <returns>An expression tree to handle ExpandoObject serialization</returns>
        public static Expression GenerateExpandoObjectExpression(Type type,
                                                                 List <ParameterExpression> variables,
                                                                 ParameterExpression outputStream,
                                                                 ParameterExpression objToSerialize,
                                                                 ParameterExpression objTracking)
        {
            var enumerableType          = typeof(IEnumerable <KeyValuePair <string, object> >);
            var getEnumeratorMethodInfo = IEnumerableMih.GetEnumerator <string, object>();
            var enumeratorMethod        = Expression.Call(Expression.Convert(objToSerialize, enumerableType), getEnumeratorMethodInfo);

            var loopBodyCargo = new EnumerableLoopBodyCargo();

            loopBodyCargo.EnumeratorType = typeof(IEnumerator <KeyValuePair <string, object> >);
            loopBodyCargo.KvpType        = typeof(KeyValuePair <string, object>);

            var preLoopActions = new List <Expression>();

            preLoopActions.Add(PrimitiveHelpers.WriteInt32(outputStream, Expression.Property(Expression.Convert(objToSerialize, typeof(ICollection <KeyValuePair <string, object> >)), CollectionMih.Count <KeyValuePair <string, object> >()), objTracking));

            var notTrackedExpressions = new List <Expression>();

            notTrackedExpressions.Add(Expression.Call(objTracking, SerializerObjectTrackerMih.TrackObject(), objToSerialize));
            notTrackedExpressions.Add(EnumerableLoopHelper.GenerateEnumeratorLoop(variables,
                                                                                  EnumerableLoopHelper.GetStringToSomethingWriter(outputStream, objTracking),
                                                                                  enumeratorMethod,
                                                                                  preLoopActions,
                                                                                  loopBodyCargo));

            return(Serializer.GenerateNullTrackedOrUntrackedExpression(type,
                                                                       outputStream,
                                                                       objToSerialize,
                                                                       objTracking,
                                                                       notTrackedExpressions,
                                                                       variables));
        }
예제 #7
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));
        }
예제 #8
0
        internal static Expression SerializeDictionary(Type type,
                                                       Type dictionaryType,
                                                       List <ParameterExpression> variables,
                                                       ParameterExpression outputStream,
                                                       ParameterExpression objToSerialize,
                                                       ParameterExpression objTracking,
                                                       bool addTracking)
        {
            MethodInfo getEnumeratorMethodInfo = type.GetMethod("GetEnumerator");
            var        enumeratorMethod        = Expression.Call(Expression.Convert(objToSerialize, type), getEnumeratorMethodInfo);

            var loopBodyCargo = new EnumerableLoopBodyCargo();

            loopBodyCargo.EnumeratorType = getEnumeratorMethodInfo.ReturnType;
            loopBodyCargo.KvpType        = typeof(KeyValuePair <,>).MakeGenericType(dictionaryType.GetGenericArguments());

            var notTrackedExpressions = new List <Expression>();

            if (addTracking)
            {
                notTrackedExpressions.Add(Expression.Call(objTracking, SerializerObjectTrackerMih.TrackObject(), objToSerialize));
                notTrackedExpressions.Add(PrimitiveHelpers.WriteByte(outputStream, Expression.Constant(SerializerObjectTracker.Value1), objTracking));
            }

            notTrackedExpressions.Add(PrimitiveHelpers.WriteInt32(outputStream, Expression.Property(Expression.Convert(objToSerialize, dictionaryType), "Count"), objTracking));

            notTrackedExpressions.Add(EnumerableLoopHelper.GenerateEnumeratorLoop(variables,
                                                                                  GetKeyValuePairLoopBodyCargo(outputStream, objTracking, "Key", dictionaryType.GetGenericArguments()[0], "Value", dictionaryType.GetGenericArguments()[1]),
                                                                                  enumeratorMethod,
                                                                                  null,
                                                                                  loopBodyCargo));

            return(Expression.Block(notTrackedExpressions));
        }
예제 #9
0
        /// <summary>
        /// Generates an expression tree to handle class type serialization
        /// </summary>
        /// <param name="outputStream">Stream to write to</param>
        /// <param name="objTracking">Reference tracker</param>
        /// <param name="item">Source object</param>
        /// <param name="itemAsObj">Source object as an object</param>
        /// <param name="typeExpr">Type of the object as an expression</param>
        /// <param name="serializer">Serializer temporary variable</param>
        /// <param name="itemType">Type of the element</param>
        /// <returns>An expression tree to handle class type serialization</returns>
        internal static Expression GetWriteClassTypeExpression(ParameterExpression outputStream,
                                                               ParameterExpression objTracking,
                                                               Expression item,
                                                               Expression itemAsObj,
                                                               ParameterExpression typeExpr,
                                                               ParameterExpression serializer,
                                                               Type itemType)
        {
            var writeType = Expression.IfThenElse(Expression.Equal(Expression.Call(item, ObjectMih.GetTypeMethod()), Expression.Constant(itemType)),
                                                  Expression.Block(PrimitiveHelpers.WriteByte(outputStream, Expression.Constant(SerializerObjectTracker.Value0), objTracking),
                                                                   Expression.Assign(typeExpr, Expression.Constant(itemType)),
                                                                   Expression.Assign(itemAsObj, Expression.Convert(item, typeof(object)))),
                                                  Expression.Block(PrimitiveHelpers.WriteByte(outputStream, Expression.Constant(SerializerObjectTracker.Value1), objTracking),
                                                                   Expression.Assign(itemAsObj, Expression.Call(SerializerMih.PrepareObjectForSerialization(), item)),
                                                                   Expression.Assign(typeExpr, Expression.Call(itemAsObj, ObjectMih.GetTypeMethod())),
                                                                   GenerateStringExpression(outputStream, Expression.Call(SerializedTypeResolverMih.GetShortNameFromType(), typeExpr), objTracking),
                                                                   PrimitiveHelpers.WriteInt32(outputStream, Expression.Call(SerializedTypeResolverMih.GetHashCodeFromType(), typeExpr), objTracking)));

            return(Expression.IfThenElse(Expression.Equal(item, Expression.Constant(null)),
                                         PrimitiveHelpers.WriteByte(outputStream, Expression.Constant(SerializerObjectTracker.Value0), objTracking),
                                         Expression.Block(PrimitiveHelpers.WriteByte(outputStream, Expression.Constant(SerializerObjectTracker.Value1), objTracking),
                                                          writeType,
                                                          Expression.Assign(serializer, Expression.Call(SerializerMih.GetTypeToObjectSerializer(), typeExpr)),
                                                          Expression.Invoke(serializer, outputStream, itemAsObj, objTracking))));
        }
예제 #10
0
        private static IEnumerable <Expression> ReadDimensionalArrayLength(ParameterExpression inputStream,
                                                                           ParameterExpression objTracker,
                                                                           Expression lengths,
                                                                           Expression i,
                                                                           Expression numberOfDimensions)
        {
            var loopExpressions = new List <Expression>();
            var expressions     = new List <Expression>();

            expressions.Add(Expression.Assign(i, Expression.Constant(0)));
            expressions.Add(Expression.Assign(numberOfDimensions, Expression.Convert(PrimitiveHelpers.ReadByte(inputStream, objTracker), typeof(int))));
            expressions.Add(Expression.Assign(lengths, Expression.Call(CreateArrayMethodInfo.GetCreateArrayMethodInfo(typeof(int)), numberOfDimensions)));

            loopExpressions.Add(Expression.Assign(Expression.ArrayAccess(lengths, i), PrimitiveHelpers.ReadInt32(inputStream, objTracker)));
            loopExpressions.Add(Expression.Assign(i, Expression.Add(i, Expression.Constant(1))));

            var loopBody   = Expression.Block(loopExpressions);
            var breakLabel = Expression.Label("breakLabel");
            var cond       = Expression.LessThan(i, numberOfDimensions);
            var loop       = Expression.Loop(Expression.IfThenElse(cond,
                                                                   loopBody,
                                                                   Expression.Break(breakLabel)),
                                             breakLabel);

            expressions.Add(loop);

            return(expressions);
        }
예제 #11
0
        internal static List <Expression> DeserializeDictionaryValues(Type type,
                                                                      List <ParameterExpression> variables,
                                                                      ParameterExpression inputStream,
                                                                      ParameterExpression objTracker,
                                                                      ParameterExpression newInstance)
        {
            var dictionaryType = DictionaryHelper.GetDictionaryType(type);
            var keyType        = dictionaryType.GetGenericArguments()[0];
            var valueType      = dictionaryType.GetGenericArguments()[1];

            var i            = Expression.Parameter(typeof(int), "i");
            var length       = Expression.Parameter(typeof(int), "length");
            var key          = Expression.Parameter(keyType, "key");
            var value        = Expression.Parameter(dictionaryType.GetGenericArguments()[1], "value");
            var typeName     = Expression.Parameter(typeof(string), "typeName");
            var typeExpr     = Expression.Parameter(typeof(TypeWithHashCode), "type");
            var deserializer = Expression.Parameter(typeof(Func <Stream, DeserializerObjectTracker, object>), "deserializer");
            var typeHashCode = Expression.Parameter(typeof(int), "typeHashCode");

            variables.Add(i);
            variables.Add(length);
            variables.Add(key);
            variables.Add(value);
            variables.Add(typeName);
            variables.Add(typeExpr);
            variables.Add(deserializer);
            variables.Add(typeHashCode);

            var loopExpressions = new List <Expression>();

            GetReadExpression(inputStream, objTracker, keyType, loopExpressions, key, typeExpr, typeName, typeHashCode, deserializer);
            GetReadExpression(inputStream, objTracker, valueType, loopExpressions, value, typeExpr, typeName, typeHashCode, deserializer);
            loopExpressions.Add(Expression.Call(newInstance, DictionaryMih.Add(dictionaryType, keyType, dictionaryType.GetGenericArguments()[1]), key, value));
            loopExpressions.Add(Expression.Assign(i, Expression.Add(i, Expression.Constant(1))));

            var cond       = Expression.LessThan(i, length);
            var loopBody   = Expression.Block(loopExpressions);
            var breakLabel = Expression.Label("breakLabel");
            var loop       = Expression.Loop(Expression.IfThenElse(cond,
                                                                   loopBody,
                                                                   Expression.Break(breakLabel)),
                                             breakLabel);

            var notTrackedExpressions = new List <Expression>();

            notTrackedExpressions.Add(Expression.Assign(length, PrimitiveHelpers.ReadInt32(inputStream, objTracker)));
            notTrackedExpressions.Add(Expression.Assign(i, Expression.Constant(0)));

            notTrackedExpressions.Add(loop);
            notTrackedExpressions.Add(newInstance);

            return(notTrackedExpressions);
        }
예제 #12
0
        private static IEnumerable <Expression> ReadJaggedArray(Type type,
                                                                Type elementType,
                                                                ParameterExpression newInstance,
                                                                List <ParameterExpression> variables,
                                                                ParameterExpression inputStream,
                                                                ParameterExpression objTracker)
        {
            var i            = Expression.Parameter(typeof(int), "i");
            var length       = Expression.Parameter(typeof(int), "length");
            var item         = Expression.Parameter(type.GetElementType(), "item");
            var typeName     = Expression.Parameter(typeof(string), "typeName");
            var typeExpr     = Expression.Parameter(typeof(TypeWithHashCode), "type");
            var typeHashCode = Expression.Parameter(typeof(int), "typeHashCode");
            var tmpValue     = Expression.Parameter(elementType, "tmpValue");
            var deserializer = Expression.Parameter(typeof(Func <Stream, DeserializerObjectTracker, object>), "deserializer");

            variables.Add(length);
            variables.Add(item);
            variables.Add(typeName);
            variables.Add(typeExpr);
            variables.Add(typeHashCode);
            variables.Add(i);
            variables.Add(tmpValue);
            variables.Add(deserializer);

            var expressions = new List <Expression>();

            expressions.Add(Expression.Assign(length, PrimitiveHelpers.ReadInt32(inputStream, objTracker)));
            expressions.Add(Expression.Assign(i, Expression.Constant(0)));
            expressions.Add(Expression.Assign(newInstance, Expression.Convert(Expression.New(type.GetConstructor(new[] { typeof(int) }), length), type)));
            if (type.IsClass)
            {
                expressions.Add(Expression.Call(objTracker, DeserializerObjectTrackerMih.TrackedObject(), newInstance));
            }

            var loopExpressions = new List <Expression>();

            loopExpressions.Add(Deserializer.GetReadClassExpression(inputStream, objTracker, tmpValue, typeExpr, typeName, typeHashCode, deserializer, elementType));
            loopExpressions.Add(Expression.Call(newInstance, ArrayMih.SetValue(), Expression.Convert(tmpValue, typeof(object)), i));
            loopExpressions.Add(Expression.Assign(i, Expression.Add(i, Expression.Constant(1))));

            var cond       = Expression.LessThan(i, length);
            var loopBody   = Expression.Block(loopExpressions);
            var breakLabel = Expression.Label("breakLabel");
            var loop       = Expression.Loop(Expression.IfThenElse(cond,
                                                                   loopBody,
                                                                   Expression.Break(breakLabel)),
                                             breakLabel);

            expressions.Add(loop);
            return(expressions);
        }
예제 #13
0
        private static Expression SerializeISerializable(Type type,
                                                         List <ParameterExpression> variables,
                                                         ParameterExpression outputStream,
                                                         ParameterExpression objToSerialize,
                                                         ParameterExpression objTracking)
        {
            var fc      = Expression.Parameter(typeof(FormatterConverter), "fc");
            var context = Expression.Parameter(typeof(StreamingContext), "context");
            var si      = Expression.Parameter(typeof(SerializationInfo), "si");
            var iser    = Expression.Parameter(typeof(ISerializable), "iser");

            variables.Add(fc);
            variables.Add(context);
            variables.Add(si);
            variables.Add(iser);

            var getEnumeratorMethodInfo = SerializationInfoMih.GetEnumerator();

            var enumeratorMethod = Expression.Call(si, getEnumeratorMethodInfo);

            var loopBodyCargo = new EnumerableLoopBodyCargo();

            loopBodyCargo.EnumeratorType = typeof(SerializationInfoEnumerator);
            loopBodyCargo.KvpType        = typeof(SerializationEntry);

            var preLoopActions = new List <Expression>();

            preLoopActions.Add(PrimitiveHelpers.WriteInt32(outputStream, Expression.Property(si, SerializationInfoMih.MemberCount()), objTracking));

            var notTrackedExpressions = new List <Expression>();

            notTrackedExpressions.Add(PrimitiveHelpers.WriteByte(outputStream, Expression.Constant(SerializerObjectTracker.Value0, typeof(byte)), objTracking));
            notTrackedExpressions.Add(Expression.Assign(fc, Expression.New(typeof(FormatterConverter))));
            notTrackedExpressions.Add(Expression.Assign(context, Expression.New(StreamingContextMih.Constructor(), Expression.Constant(StreamingContextStates.All))));
            notTrackedExpressions.Add(Expression.Assign(si, Expression.New(SerializationInfoMih.Constructor(), Expression.Constant(type), fc)));
            notTrackedExpressions.Add(Expression.Assign(iser, Expression.Convert(objToSerialize, typeof(ISerializable))));
            notTrackedExpressions.AddRange(SerializationCallbacksHelper.GenerateOnSerializingAttributeExpression(type, objToSerialize, context));
            notTrackedExpressions.Add(Expression.Call(iser, ISerializableMih.GetObjectData(), si, context));
            notTrackedExpressions.AddRange(SerializationCallbacksHelper.GenerateOnSerializedAttributeExpression(type, objToSerialize, context));
            notTrackedExpressions.Add(Expression.IfThen(Expression.IsTrue(Expression.Property(si, "IsFullTypeNameSetExplicit")),
                                                        Expression.Throw(Expression.New(InvalidOperationExceptionMih.Constructor(), Expression.Constant("Changing the full type name for an ISerializable is not supported")))));
            notTrackedExpressions.Add(Expression.IfThen(Expression.IsTrue(Expression.Property(si, "IsAssemblyNameSetExplicit")),
                                                        Expression.Throw(Expression.New(InvalidOperationExceptionMih.Constructor(), Expression.Constant("Changing the assembly name for an ISerializable is not supported")))));
            notTrackedExpressions.Add(EnumerableLoopHelper.GenerateEnumeratorLoop(variables,
                                                                                  DictionarySerializer.GetKeyValuePairLoopBodyCargo(outputStream, objTracking, "Name", typeof(string), "Value", typeof(object)),
                                                                                  enumeratorMethod,
                                                                                  preLoopActions,
                                                                                  loopBodyCargo));
            notTrackedExpressions.Add(Expression.Call(objTracking, SerializerObjectTrackerMih.TrackObject(), objToSerialize));

            return(Expression.Block(notTrackedExpressions));
        }
예제 #14
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));
        }
예제 #15
0
        private static IEnumerable <Expression> WriteJaggedArray(Type elementType,
                                                                 List <ParameterExpression> variables,
                                                                 ParameterExpression outputStream,
                                                                 ParameterExpression arr,
                                                                 ParameterExpression objTracking)
        {
            var item       = Expression.Parameter(elementType, "item");
            var serializer = Expression.Parameter(typeof(Action <Stream, object, SerializerObjectTracker>), "serializer");
            var itemAsObj  = Expression.Parameter(typeof(object), "itemAsObj");
            var typeExpr   = Expression.Parameter(typeof(Type), "typeExpr");
            var i          = Expression.Parameter(typeof(int), "i");
            var length     = Expression.Parameter(typeof(int), "length");

            variables.Add(typeExpr);
            variables.Add(itemAsObj);
            variables.Add(serializer);
            variables.Add(item);
            variables.Add(length);
            variables.Add(i);

            var expressions = new List <Expression>();

            expressions.Add(Expression.Assign(length, Expression.Property(arr, "Length")));
            expressions.Add(PrimitiveHelpers.WriteInt32(outputStream, length, objTracking));
            expressions.Add(Expression.Assign(i, Expression.Constant(0)));

            Debug.Assert(!elementType.IsPrimitive && !elementType.IsValueType && elementType != typeof(string), "Type cannot be a primitive");

            var loopExpressions = new List <Expression>();

            loopExpressions.Add(Expression.Assign(item, Expression.ArrayAccess(arr, i)));   // uh?
            loopExpressions.Add(Expression.Assign(item, Expression.Convert(Expression.Call(arr, ArrayMih.GetValue(), i), elementType)));
            loopExpressions.Add(Serializer.GetWriteClassTypeExpression(outputStream, objTracking, item, itemAsObj, typeExpr, serializer, elementType));
            loopExpressions.Add(Expression.Assign(i, Expression.Add(i, Expression.Constant(1))));

            var cond     = Expression.LessThan(i, length);
            var loopBody = Expression.Block(loopExpressions);

            var breakLabel = Expression.Label("breakLabel");
            var loop       = Expression.Loop(Expression.IfThenElse(cond,
                                                                   loopBody,
                                                                   Expression.Break(breakLabel)),
                                             breakLabel);

            expressions.Add(loop);

            return(expressions);
        }
예제 #16
0
        /// <summary>
        /// Generates an expression tree to handle string serialization
        /// </summary>
        /// <param name="outputStream">Stream to write to</param>
        /// <param name="objToSerialize">Object to serialize</param>
        /// <param name="objTracking">Reference tracker</param>
        /// <returns>An expression tree to handle string serialization</returns>
        internal static Expression GenerateStringExpression(ParameterExpression outputStream,
                                                            Expression objToSerialize,
                                                            ParameterExpression objTracking)
        {
            List <Expression>          notTrackedExpressions = new List <Expression>();
            List <ParameterExpression> variables             = new List <ParameterExpression>();

            notTrackedExpressions.Add(Expression.Call(objTracking, SerializerObjectTrackerMih.TrackObject(), objToSerialize));
            notTrackedExpressions.Add(PrimitiveHelpers.WriteString(outputStream, objToSerialize, objTracking));

            return(GenerateNullTrackedOrUntrackedExpression(typeof(string),
                                                            outputStream,
                                                            objToSerialize,
                                                            objTracking,
                                                            notTrackedExpressions,
                                                            variables));
        }
예제 #17
0
        /// <summary>
        /// Generate an expression to handle the 'is the object null' case
        /// </summary>
        /// <param name="type">Type of the object</param>
        /// <param name="inputStream">Stream to read from</param>
        /// <param name="objTracker">Reference tracker</param>
        /// <param name="newInstance">New deserialized object</param>
        /// <param name="notTrackedExpressions">Expressions to execute if the object is not tracked</param>
        /// <param name="trackType">Type of the tracked object</param>
        /// <param name="variables">Global variables for the expression tree</param>
        /// <returns>An expression tree to handle the 'is the object null' case</returns>
        internal static Expression GenerateNullTrackedOrUntrackedExpression(Type type,
                                                                            ParameterExpression inputStream,
                                                                            ParameterExpression objTracker,
                                                                            ParameterExpression newInstance,
                                                                            List <Expression> notTrackedExpressions,
                                                                            ParameterExpression trackType,
                                                                            List <ParameterExpression> variables)
        {
            var alreadyTrackedExpr = Expression.Assign(newInstance, Expression.Convert(Expression.Call(objTracker, DeserializerObjectTrackerMih.GetTrackedObject(), PrimitiveHelpers.ReadInt32(inputStream, objTracker)), type));

            var notAlreadyTrackedExpr = Expression.Block(notTrackedExpressions);
            var isNotNullExpr         = Expression.Block(Expression.Assign(trackType, Expression.Convert(PrimitiveHelpers.ReadByte(inputStream, objTracker), typeof(byte))),
                                                         Expression.IfThenElse(Expression.Equal(trackType, Expression.Constant(SerializerObjectTracker.Value0)),
                                                                               alreadyTrackedExpr,
                                                                               notAlreadyTrackedExpr));

            var expr = Expression.IfThenElse(Expression.Equal(Expression.Convert(PrimitiveHelpers.ReadByte(inputStream, objTracker), typeof(byte)), Expression.Constant(SerializerObjectTracker.Value0)),
                                             Expression.Assign(newInstance, Expression.Convert(Expression.Constant(null), type)),
                                             isNotNullExpr);

            return(Expression.Block(variables, expr, newInstance));
        }
예제 #18
0
        private static Expression DeserializeISerializable(Type type,
                                                           List <ParameterExpression> variables,
                                                           ParameterExpression inputStream,
                                                           ParameterExpression objTracker,
                                                           ParameterExpression newInstance)
        {
            var length       = Expression.Parameter(typeof(int), "length");
            var i            = Expression.Parameter(typeof(int), "i");
            var key          = Expression.Parameter(typeof(string), "key");
            var value        = Expression.Parameter(typeof(object), "value");
            var typeName     = Expression.Parameter(typeof(string), "typeName");
            var typeExpr     = Expression.Parameter(typeof(TypeWithHashCode), "type");
            var deserializer = Expression.Parameter(typeof(Func <Stream, DeserializerObjectTracker, object>), "deserializer");
            var typeHashCode = Expression.Parameter(typeof(int), "typeHashCode");
            var fc           = Expression.Parameter(typeof(FormatterConverter), "fc");
            var context      = Expression.Parameter(typeof(StreamingContext), "context");
            var si           = Expression.Parameter(typeof(SerializationInfo), "si");

            variables.Add(fc);
            variables.Add(context);
            variables.Add(si);
            variables.Add(key);
            variables.Add(value);
            variables.Add(length);
            variables.Add(i);
            variables.Add(deserializer);
            variables.Add(typeName);
            variables.Add(typeExpr);
            variables.Add(typeHashCode);

            var loopExpressions = new List <Expression>();

            DictionaryDeserializer.GetReadExpression(inputStream, objTracker, typeof(string), loopExpressions, key, typeExpr, typeName, typeHashCode, deserializer);
            DictionaryDeserializer.GetReadExpression(inputStream, objTracker, typeof(object), loopExpressions, value, typeExpr, typeName, typeHashCode, deserializer);
            loopExpressions.Add(Expression.Call(si, SerializationInfoMih.AddValue(), key, value));
            loopExpressions.Add(Expression.Assign(i, Expression.Add(i, Expression.Constant(1))));

            var cond       = Expression.LessThan(i, length);
            var loopBody   = Expression.Block(loopExpressions);
            var breakLabel = Expression.Label("breakLabel");
            var loop       = Expression.Loop(Expression.IfThenElse(cond,
                                                                   loopBody,
                                                                   Expression.Break(breakLabel)),
                                             breakLabel);

            var notTrackedExpressions = new List <Expression>();

            notTrackedExpressions.Add(Expression.Assign(fc, Expression.New(typeof(FormatterConverter))));
            notTrackedExpressions.Add(Expression.Assign(context, Expression.New(StreamingContextMih.Constructor(), Expression.Constant(StreamingContextStates.All))));
            notTrackedExpressions.Add(Expression.Assign(si, Expression.New(SerializationInfoMih.Constructor(), Expression.Constant(type), fc)));
            notTrackedExpressions.Add(Expression.Assign(length, PrimitiveHelpers.ReadInt32(inputStream, objTracker)));
            notTrackedExpressions.Add(Expression.Assign(i, Expression.Constant(0)));
            notTrackedExpressions.Add(loop);
            notTrackedExpressions.Add(Expression.Assign(newInstance, Expression.New(ISerializableSerializer.GetSerializationConstructor(type), si, context)));
            if (type.IsClass)
            {
                notTrackedExpressions.Add(Expression.Call(objTracker, DeserializerObjectTrackerMih.TrackedObject(), newInstance));
            }

            notTrackedExpressions.AddRange(SerializationCallbacksHelper.GenerateOnDeserializedAttributeExpression(type, newInstance, context));
            notTrackedExpressions.Add(SerializationCallbacksHelper.GenerateCallIDeserializationExpression(type, newInstance));
            notTrackedExpressions.Add(newInstance);

            return(Expression.Block(notTrackedExpressions));
        }
예제 #19
0
        public static Expression GenerateDictionaryGenericExpression(Type type,
                                                                     List <ParameterExpression> variables,
                                                                     ParameterExpression inputStream,
                                                                     ParameterExpression objTracker)
        {
            var ctor = type.GetConstructor(new Type[0]);

            if (ctor == null)
            {
                throw new MissingConstructorException("Type " + type + " must have a public constructor without parameter.");
            }

            var notTrackedExpressions = new List <Expression>();
            var newInstance           = Expression.Parameter(type, "newInstanceDict");
            var comparerType          = Expression.Parameter(typeof(byte), "comparerType");

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

            variables.Add(deserializer);
            variables.Add(typeExpr);
            variables.Add(typeName);
            variables.Add(typeHashCode);


            variables.Add(newInstance);
            variables.Add(comparerType);

            var genericDictionaryType = DictionaryHelper.GetDictionaryType(type);
            var comparerConstructor   = DictionaryHelper.GetComparerConstructor(type);

            var deserializeDictionaryWithDefaultComparer = DeserializeDictionary(type,
                                                                                 genericDictionaryType,
                                                                                 variables,
                                                                                 newInstance,
                                                                                 inputStream,
                                                                                 objTracker,
                                                                                 deserializer,
                                                                                 typeExpr,
                                                                                 typeName,
                                                                                 typeHashCode,
                                                                                 (exprs, newIns) => exprs.Add(Expression.Assign(newIns, Expression.New(type.GetConstructor(new Type[0])))));

            if (comparerConstructor == null)
            {
                notTrackedExpressions.Add(PrimitiveHelpers.ReadByte(inputStream, objTracker));
                notTrackedExpressions.Add(deserializeDictionaryWithDefaultComparer);
            }
            else
            {
                notTrackedExpressions.Add(Expression.IfThenElse(Expression.Equal(PrimitiveHelpers.ReadByte(inputStream, objTracker), Expression.Constant(0, typeof(int))),
                                                                deserializeDictionaryWithDefaultComparer,
                                                                DeserializeDictionary(type,
                                                                                      genericDictionaryType,
                                                                                      variables,
                                                                                      newInstance,
                                                                                      inputStream,
                                                                                      objTracker,
                                                                                      deserializer,
                                                                                      typeExpr,
                                                                                      typeName,
                                                                                      typeHashCode,
                                                                                      (exprs, newIns) =>
                {
                    var eqType   = typeof(IEqualityComparer <>).MakeGenericType(genericDictionaryType.GetGenericArguments()[0]);
                    var comparer = Expression.Parameter(eqType, "comparer");
                    variables.Add(comparer);
                    exprs.Add(Deserializer.GetReadClassExpression(inputStream,
                                                                  objTracker,
                                                                  comparer,
                                                                  typeExpr,
                                                                  typeName,
                                                                  typeHashCode,
                                                                  deserializer,
                                                                  eqType));
                    exprs.Add(Expression.Assign(newIns, Expression.New(comparerConstructor, comparer)));
                })));
            }



            return(Deserializer.GenerateNullTrackedOrUntrackedExpression(type,
                                                                         inputStream,
                                                                         objTracker,
                                                                         newInstance,
                                                                         notTrackedExpressions,
                                                                         comparerType,
                                                                         variables));
        }
예제 #20
0
        /// <summary>
        /// Generates an expression tree to deserialize an ExpandoObject
        /// </summary>
        /// <param name="variables">Global variables for the expression tree</param>
        /// <param name="inputStream">Stream to read from</param>
        /// <param name="objTracker">Reference tracker</param>
        /// <returns>An expression tree to deserialize an ExpandoObject</returns>
        internal static Expression GenerateExpandoObjectExpression(List <ParameterExpression> variables,
                                                                   ParameterExpression inputStream,
                                                                   ParameterExpression objTracker)
        {
            var dictType     = typeof(IDictionary <string, object>);
            var length       = Expression.Parameter(typeof(int), "length");
            var i            = Expression.Parameter(typeof(int), "i");
            var key          = Expression.Parameter(typeof(string), "key");
            var value        = Expression.Parameter(typeof(object), "value");
            var typeName     = Expression.Parameter(typeof(string), "typeName");
            var typeExpr     = Expression.Parameter(typeof(TypeWithHashCode), "type");
            var deserializer = Expression.Parameter(typeof(Func <Stream, DeserializerObjectTracker, object>), "deserializer");
            var newInstance  = Expression.Parameter(typeof(ExpandoObject), "newInstance");
            var destDict     = Expression.Parameter(dictType, "destDict");
            var typeHashCode = Expression.Parameter(typeof(int), "typeHashCode");
            var trackType    = Expression.Parameter(typeof(byte), "trackType");

            variables.Add(key);
            variables.Add(value);
            variables.Add(length);
            variables.Add(i);
            variables.Add(deserializer);
            variables.Add(typeName);
            variables.Add(typeExpr);
            variables.Add(newInstance);
            variables.Add(destDict);
            variables.Add(typeHashCode);
            variables.Add(trackType);

            var loopExpressions = new List <Expression>();

            loopExpressions.Add(Expression.Assign(key, Deserializer.GenerateStringExpression(inputStream, objTracker)));
            loopExpressions.Add(Deserializer.GetReadClassExpression(inputStream, objTracker, value, typeExpr, typeName, typeHashCode, deserializer, typeof(object)));
            loopExpressions.Add(Expression.Call(destDict, DictionaryMih.Add <string, object>(), key, value));
            loopExpressions.Add(Expression.Assign(i, Expression.Add(i, Expression.Constant(1))));

            var cond       = Expression.LessThan(i, length);
            var loopBody   = Expression.Block(loopExpressions);
            var breakLabel = Expression.Label("breakLabel");
            var loop       = Expression.Loop(Expression.IfThenElse(cond,
                                                                   loopBody,
                                                                   Expression.Break(breakLabel)),
                                             breakLabel);

            var notTrackedExpressions = new List <Expression>();

            notTrackedExpressions.Add(Expression.Assign(length, PrimitiveHelpers.ReadInt32(inputStream, objTracker)));
            notTrackedExpressions.Add(Expression.Assign(i, Expression.Constant(0)));
            notTrackedExpressions.Add(Expression.Assign(newInstance, Expression.New(typeof(ExpandoObject))));
            notTrackedExpressions.Add(Expression.Assign(destDict, Expression.Convert(newInstance, dictType)));
            notTrackedExpressions.Add(Expression.Call(objTracker, DeserializerObjectTrackerMih.TrackedObject(), newInstance));

            notTrackedExpressions.Add(loop);

            return(Deserializer.GenerateNullTrackedOrUntrackedExpression(typeof(ExpandoObject),
                                                                         inputStream,
                                                                         objTracker,
                                                                         newInstance,
                                                                         notTrackedExpressions,
                                                                         trackType,
                                                                         variables));
        }