/// <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)); }
/// <summary> /// Generate an expression tree that clones ExpandoObject /// </summary> /// <param name="variables">Global variables for the expression tree</param> /// <param name="source">Source object</param> /// <param name="clone">Clone object</param> /// <param name="refTrackerParam">Reference tracker</param> /// <returns>An expression tree that clones ExpandoObject</returns> public static Expression GenerateExpandoObjectExpression(List <ParameterExpression> variables, ParameterExpression source, ParameterExpression clone, ParameterExpression refTrackerParam) { var enumerableType = typeof(IEnumerable <KeyValuePair <string, object> >); var getEnumeratorMethodInfo = IEnumerableMih.GetEnumerator <string, object>(); var enumeratorMethod = Expression.Call(Expression.Convert(source, enumerableType), getEnumeratorMethodInfo); var dictType = typeof(IDictionary <string, object>); var cloneAsDict = Expression.Parameter(dictType, "cloneDict"); var expressions = new List <Expression>(); variables.Add(cloneAsDict); expressions.Add(Expression.Assign(clone, Expression.New(typeof(ExpandoObject)))); expressions.Add(Expression.Assign(cloneAsDict, Expression.Convert(clone, dictType))); expressions.Add(Expression.Call(refTrackerParam, ObjectClonerReferenceTrackerMih.Track(), source, clone)); var loopBodyCargo = new EnumerableLoopBodyCargo(); loopBodyCargo.EnumeratorType = typeof(IEnumerator <KeyValuePair <string, object> >); loopBodyCargo.KvpType = typeof(KeyValuePair <string, object>); expressions.Add(EnumerableLoopHelper.GenerateEnumeratorLoop(variables, CloneKeyValuePair(clone, refTrackerParam), enumeratorMethod, null, loopBodyCargo)); return(ObjectCloner.GenerateNullTrackedOrUntrackedExpression(source, clone, typeof(ExpandoObject), refTrackerParam, Expression.Block(expressions))); }
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)); }
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 GetWriteExpression(ParameterExpression outputStream, ParameterExpression objTracking, Type valueType, MemberExpression valueExpression, EnumerableLoopBodyCargo cargo) { if (valueType == typeof(string)) { return(Serializer.GenerateStringExpression(outputStream, valueExpression, objTracking)); } if (valueType.IsPrimitive || valueType.IsValueType) { var primitiveSerializer = Serializer.GetTypeSerializer(valueType); return(Expression.Invoke(Expression.Constant(primitiveSerializer), outputStream, valueExpression, objTracking)); } return(Serializer.GetWriteClassTypeExpression(outputStream, objTracking, valueExpression, cargo.ItemAsObj, cargo.TypeExpr, cargo.Serializer, valueType)); }
/// <summary> /// Generates an expression tree to clone an ISerializable /// </summary> /// <param name="variables">Global variables for the expression tree</param> /// <param name="source">Source object</param> /// <param name="clone">Clone object</param> /// <param name="sourceType">Type of the source object</param> /// <param name="refTrackerParam">Reference tracker</param> /// <returns>An expression tree to clone an ISerializable</returns> public static Expression GenerateISerializableExpression(List <ParameterExpression> variables, ParameterExpression source, ParameterExpression clone, Type sourceType, ParameterExpression refTrackerParam) { var serializationConstructor = ISerializableSerializer.GetSerializationConstructor(sourceType); if (serializationConstructor == null) { throw new MissingConstructorException("Cannot serialize type " + sourceType + " because it does not have the required constructor for ISerializable. If you inherits from a class that implements ISerializable you have to expose the serialization constructor."); } var getEnumeratorMethodInfo = SerializationInfoMih.GetEnumerator(); var siSource = Expression.Parameter(typeof(SerializationInfo), "siSource"); var fc = Expression.Parameter(typeof(FormatterConverter), "fc"); var context = Expression.Parameter(typeof(StreamingContext), "context"); var iserSource = Expression.Parameter(typeof(ISerializable), "iserSource"); var siClone = Expression.Parameter(typeof(SerializationInfo), "siClone"); var cloner = Expression.Parameter(typeof(Func <object, ObjectClonerReferenceTracker, object>), "cloner"); var clonedItem = Expression.Parameter(typeof(object), "clonedItem"); variables.Add(fc); variables.Add(context); variables.Add(siSource); variables.Add(iserSource); variables.Add(siClone); variables.Add(cloner); variables.Add(clonedItem); var enumeratorMethod = Expression.Call(siSource, getEnumeratorMethodInfo); var loopBodyCargo = new EnumerableLoopBodyCargo(); loopBodyCargo.EnumeratorType = typeof(SerializationInfoEnumerator); loopBodyCargo.KvpType = typeof(SerializationEntry); var expressions = new List <Expression>(); expressions.Add(Expression.Assign(fc, Expression.New(typeof(FormatterConverter)))); expressions.Add(Expression.Assign(context, Expression.New(StreamingContextMih.Constructor(), Expression.Constant(StreamingContextStates.All)))); expressions.Add(Expression.Assign(siSource, Expression.New(SerializationInfoMih.Constructor(), Expression.Constant(sourceType), fc))); expressions.Add(Expression.Assign(iserSource, Expression.Convert(source, typeof(ISerializable)))); expressions.Add(Expression.Assign(siClone, Expression.New(SerializationInfoMih.Constructor(), Expression.Constant(sourceType), fc))); expressions.AddRange(SerializationCallbacksHelper.GenerateOnSerializingAttributeExpression(sourceType, source, context)); expressions.Add(Expression.Call(iserSource, ISerializableMih.GetObjectData(), siSource, context)); expressions.AddRange(SerializationCallbacksHelper.GenerateOnSerializedAttributeExpression(sourceType, source, context)); expressions.Add(Expression.IfThen(Expression.IsTrue(Expression.Property(siSource, "IsFullTypeNameSetExplicit")), Expression.Throw(Expression.New(InvalidOperationExceptionMih.Constructor(), Expression.Constant("Changing the full type name for an ISerializable is not supported"))))); expressions.Add(Expression.IfThen(Expression.IsTrue(Expression.Property(siSource, "IsAssemblyNameSetExplicit")), Expression.Throw(Expression.New(InvalidOperationExceptionMih.Constructor(), Expression.Constant("Changing the assembly name for an ISerializable is not supported"))))); expressions.Add(EnumerableLoopHelper.GenerateEnumeratorLoop(variables, GetLoopBodyCargo(siClone, clonedItem, refTrackerParam), enumeratorMethod, null, loopBodyCargo)); expressions.Add(Expression.Assign(clone, Expression.New(serializationConstructor, siClone, context))); expressions.Add(Expression.Call(refTrackerParam, ObjectClonerReferenceTrackerMih.Track(), source, clone)); expressions.AddRange(SerializationCallbacksHelper.GenerateOnDeserializedAttributeExpression(sourceType, clone, context)); expressions.Add(SerializationCallbacksHelper.GenerateCallIDeserializationExpression(sourceType, clone)); return(ObjectCloner.GenerateNullTrackedOrUntrackedExpression(source, clone, sourceType, refTrackerParam, Expression.Block(expressions))); }