/// <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)); }
/// <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)))); }
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); }
/// <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)); }
/// <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)); }
/// <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)); }
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)); }
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)); }
/// <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)))); }
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); }
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); }
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); }
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)); }
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)); }
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); }
/// <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)); }
/// <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)); }
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)); }
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)); }
/// <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)); }