/// <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)); }
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 jagged array serialization /// </summary> /// <param name="type">Type of array</param> /// <param name="elementType">Type of the elements contained in the array</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 jagged array serialization</returns> internal static Expression GenerateJaggedArray(Type type, Type elementType, ParameterExpression outputStream, ParameterExpression objToSerialize, ParameterExpression objTracking) { List <Expression> notTrackedExpressions = new List <Expression>(); List <ParameterExpression> variables = new List <ParameterExpression>(); var trackedObjectPosition = Expression.Parameter(typeof(int?), "trackedObjectPosition"); var arr = Expression.Parameter(type, "arr"); variables.Add(trackedObjectPosition); variables.Add(arr); notTrackedExpressions.Add(Expression.Call(objTracking, SerializerObjectTrackerMih.TrackObject(), objToSerialize)); notTrackedExpressions.Add(Expression.Assign(arr, Expression.Convert(objToSerialize, type))); notTrackedExpressions.AddRange(WriteJaggedArray(elementType, variables, outputStream, arr, objTracking)); return(Serializer.GenerateNullTrackedOrUntrackedExpression(type, outputStream, objToSerialize, objTracking, notTrackedExpressions, variables)); }
internal static void GenerateFieldsExpression(Type type, FieldInfo[] fields, ParameterExpression outputStream, Expression objToSerialize, ParameterExpression objTracking, List <ParameterExpression> variables, List <Expression> notTrackedExpressions) { 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> copyFieldsExpressions = new List <Expression>(); if (type.IsClass) { copyFieldsExpressions.Add(Expression.Call(objTracking, SerializerObjectTrackerMih.TrackObject(), objToSerialize)); } notTrackedExpressions.AddRange(SerializationCallbacksHelper.GenerateOnSerializingAttributeExpression(type, objToSerialize, Expression.New(StreamingContextMih.Constructor(), Expression.Constant(StreamingContextStates.All)))); foreach (var fieldInfo in fields) { var fieldValueExpr = Expression.Field(Expression.Convert(objToSerialize, type), fieldInfo); if (fieldInfo.FieldType == typeof(string)) { copyFieldsExpressions.Add(GenerateStringExpression(outputStream, fieldValueExpr, objTracking)); } else if (fieldInfo.FieldType.IsPrimitive || fieldInfo.FieldType.IsValueType) { var primitiveWriter = GetPrimitiveWriter(fieldInfo.FieldType); if (primitiveWriter == null) { var primitiveSerializer = GetTypeSerializer(fieldInfo.FieldType); copyFieldsExpressions.Add(Expression.Invoke(Expression.Constant(primitiveSerializer), outputStream, fieldValueExpr, objTracking)); } else { copyFieldsExpressions.Add(primitiveWriter(outputStream, fieldValueExpr, objTracking)); } } else { copyFieldsExpressions.Add(GetWriteClassTypeExpression(outputStream, objTracking, fieldValueExpr, itemAsObj, typeExpr, serializer, fieldInfo.FieldType)); } } notTrackedExpressions.AddRange(copyFieldsExpressions); notTrackedExpressions.AddRange(SerializationCallbacksHelper.GenerateOnSerializedAttributeExpression(type, objToSerialize, Expression.New(StreamingContextMih.Constructor(), Expression.Constant(StreamingContextStates.All)))); }
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)); }
/// <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 tree to handle array serialization /// </summary> /// <param name="type">Type of the array</param> /// <param name="elementType">Type of the elements contained inside the array</param> /// <param name="outputStream">Stream that is written to</param> /// <param name="objToSerialize">Object to serialize</param> /// <param name="objTracking">Reference tracker</param> /// <returns>An expression tree to handle array serialization</returns> internal static Expression GenerateArrayOfKnownDimension(Type type, Type elementType, ParameterExpression outputStream, ParameterExpression objToSerialize, ParameterExpression objTracking) { List <Expression> notTrackedExpressions = new List <Expression>(); List <ParameterExpression> variables = new List <ParameterExpression>(); var i = Expression.Parameter(typeof(int), "i"); var lengths = Expression.Parameter(typeof(int[]), "lengths"); var trackedObjectPosition = Expression.Parameter(typeof(int?), "trackedObjectPosition"); var arr = Expression.Parameter(type, "arr"); var rank = type.GetArrayRank(); variables.Add(trackedObjectPosition); variables.Add(i); variables.Add(lengths); variables.Add(arr); notTrackedExpressions.Add(Expression.Call(objTracking, SerializerObjectTrackerMih.TrackObject(), objToSerialize)); notTrackedExpressions.Add(Expression.Assign(arr, Expression.Convert(objToSerialize, type))); notTrackedExpressions.Add(Expression.Assign(lengths, Expression.Call(CreateArrayMethodInfo.GetCreateArrayMethodInfo(typeof(int)), Expression.Constant(rank)))); notTrackedExpressions.Add(Expression.Assign(i, Expression.Constant(0))); notTrackedExpressions.Add(Expression.IfThen(Expression.GreaterThanOrEqual(Expression.Constant(rank), Expression.Constant(255)), Expression.Throw(Expression.New(NotSupportedExceptionMih.ConstructorString(), Expression.Constant("Array with more than 255 dimensions are not supported"))))); notTrackedExpressions.AddRange(WriteDimensionalArrayLength(outputStream, objTracking, i, arr, lengths, rank)); notTrackedExpressions.AddRange(WriteDimensionalArray(elementType, variables, outputStream, arr, rank, lengths, objTracking)); return(Serializer.GenerateNullTrackedOrUntrackedExpression(type, outputStream, objToSerialize, objTracking, notTrackedExpressions, variables)); }
/// <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)); }