/// <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)); }
private static Expression GenerateClassExpression(Type type, ParameterExpression inputStream, ParameterExpression objTracker) { List <ParameterExpression> variables = new List <ParameterExpression>(); var trackType = Expression.Parameter(typeof(byte), "isAlreadyTracked"); var newInstance = Expression.Parameter(type, "newInstance"); var deserializer = Expression.Parameter(typeof(Func <Stream, DeserializerObjectTracker, object>), "deserializer"); var typeExpr = Expression.Parameter(typeof(TypeWithHashCode), "typeExpr"); var typeName = Expression.Parameter(typeof(string), "typeName"); var typeHashCode = Expression.Parameter(typeof(int), "typeHashCode"); variables.Add(trackType); variables.Add(newInstance); variables.Add(deserializer); variables.Add(typeExpr); variables.Add(typeName); variables.Add(typeHashCode); var temporaryVariables = new Dictionary <Type, ParameterExpression>(); List <Expression> notTrackedExpressions = new List <Expression>(); notTrackedExpressions.Add(Expression.Assign(newInstance, Expression.Convert(Expression.Call(FormatterServicesMih.GetUninitializedObject(), Expression.Constant(type)), type))); notTrackedExpressions.AddRange(SerializationCallbacksHelper.GenerateOnDeserializingAttributeExpression(type, newInstance, Expression.New(StreamingContextMih.Constructor(), Expression.Constant(StreamingContextStates.All)))); if (type.IsClass) { notTrackedExpressions.Add(Expression.Call(objTracker, DeserializerObjectTrackerMih.TrackedObject(), newInstance)); } GenerateReadFieldsExpression(type, InternalSerializationStuff.GetFields(type), inputStream, objTracker, temporaryVariables, variables, newInstance, notTrackedExpressions, typeExpr, typeName, typeHashCode, deserializer); notTrackedExpressions.AddRange(SerializationCallbacksHelper.GenerateOnDeserializedAttributeExpression(type, newInstance, Expression.New(StreamingContextMih.Constructor(), Expression.Constant(StreamingContextStates.All)))); notTrackedExpressions.Add(SerializationCallbacksHelper.GenerateCallIDeserializationExpression(type, newInstance)); return(Deserializer.GenerateNullTrackedOrUntrackedExpression(type, inputStream, objTracker, newInstance, notTrackedExpressions, trackType, variables)); }
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 DeserializeDictionary(Type type, Type genericDictionaryType, List <ParameterExpression> variables, ParameterExpression newInstance, ParameterExpression inputStream, ParameterExpression objTracker, ParameterExpression deserializer, ParameterExpression typeExpr, ParameterExpression typeName, ParameterExpression typeHashCode, Action <List <Expression>, ParameterExpression> createClassAction) { var expressions = new List <Expression>(); var trackType = Expression.Parameter(typeof(byte), "isAlreadyTracked"); variables.Add(trackType); var temporaryVariables = new Dictionary <Type, ParameterExpression>(); var fields = InternalSerializationStuff.GetFields(type, genericDictionaryType); createClassAction(expressions, newInstance); expressions.Add(Expression.Call(objTracker, DeserializerObjectTrackerMih.TrackedObject(), newInstance)); Deserializer.GenerateReadFieldsExpression(type, fields, inputStream, objTracker, temporaryVariables, variables, newInstance, expressions, typeExpr, typeName, typeHashCode, deserializer); expressions.AddRange(DeserializeDictionaryValues(type, variables, inputStream, objTracker, newInstance)); //expressions.AddRange(SerializationCallbacksHelper.GenerateOnDeserializedAttributeExpression(type, newInstance, Expression.New(StreamingContextMih.Constructor(), Expression.Constant(StreamingContextStates.All)))); //expressions.Add(SerializationCallbacksHelper.GenerateCallIDeserializationExpression(type, newInstance)); return(Expression.Block(expressions)); }
private static Expression DeserializeDictionary(Type type, List <ParameterExpression> variables, ParameterExpression inputStream, ParameterExpression objTracker, ParameterExpression newInstance) { var notTrackedExpressions = new List <Expression>(); notTrackedExpressions.Add(Expression.Assign(newInstance, Expression.New(type.GetConstructor(new Type[0])))); notTrackedExpressions.Add(Expression.Call(objTracker, DeserializerObjectTrackerMih.TrackedObject(), newInstance)); notTrackedExpressions.AddRange(DictionaryDeserializer.DeserializeDictionaryValues(type, variables, inputStream, objTracker, newInstance)); return(Expression.Block(notTrackedExpressions)); }
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)); }
/// <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)); }
private static IEnumerable <Expression> ReadDimensionalArray(Type type, Type elementType, ParameterExpression newInstance, List <ParameterExpression> variables, ParameterExpression inputStream, ParameterExpression lengths, ParameterExpression objTracker, int rank) { var typeName = Expression.Parameter(typeof(string), "typeName"); var typeExpr = Expression.Parameter(typeof(TypeWithHashCode), "type"); var indices = Expression.Parameter(typeof(int[]), "indices"); var tmpValue = Expression.Parameter(elementType, "tmpValue"); var deserializer = Expression.Parameter(typeof(Func <Stream, DeserializerObjectTracker, object>), "deserializer"); var typeHashCode = Expression.Parameter(typeof(int), "typeHashCode"); variables.Add(deserializer); variables.Add(typeName); variables.Add(typeExpr); variables.Add(tmpValue); variables.Add(typeHashCode); var expressions = new List <Expression>(); expressions.Add(Expression.Assign(newInstance, Expression.Convert(Expression.Call(ArrayMih.CreateInstance(), Expression.Constant(elementType), lengths), type))); if (type.IsClass) { expressions.Add(Expression.Call(objTracker, DeserializerObjectTrackerMih.TrackedObject(), newInstance)); } if (rank > 1) { variables.Add(indices); expressions.Add(Expression.Assign(indices, Expression.Call(CreateArrayMethodInfo.GetCreateArrayMethodInfo(typeof(int)), Expression.Property(lengths, "Length")))); } Expression innerExpression; if (elementType == typeof(string)) { innerExpression = Expression.Assign(tmpValue, Deserializer.GenerateStringExpression(inputStream, objTracker)); } else if (elementType.IsPrimitive || elementType.IsValueType) { var primitiveReader = Deserializer.GetPrimitiveReader(elementType); if (primitiveReader == null) { var primitiveDeserializer = Deserializer.GetTypeDeserializer(elementType); innerExpression = Expression.Assign(tmpValue, Expression.Convert(Expression.Invoke(Expression.Constant(primitiveDeserializer), inputStream, objTracker), elementType)); } else { if (elementType == typeof(byte) || elementType == typeof(sbyte) || elementType == typeof(byte?) || elementType == typeof(sbyte?) || Deserializer.IsEnumOrNullableEnum(elementType)) { innerExpression = Expression.Assign(tmpValue, Expression.Convert(primitiveReader(inputStream, objTracker), elementType)); } else { innerExpression = Expression.Assign(tmpValue, primitiveReader(inputStream, objTracker)); } } } else { innerExpression = Deserializer.GetReadClassExpression(inputStream, objTracker, tmpValue, typeExpr, typeName, typeHashCode, deserializer, elementType); } Func <int, Expression, Expression> readArrayLoop = (loopRank, innerExpr) => { var loopRankIndex = Expression.Parameter(typeof(int), "loopRankIndex" + loopRank); variables.Add(loopRankIndex); var loopExpressions = new List <Expression>(); if (rank == 1) { loopExpressions.Add(innerExpr); loopExpressions.Add(Expression.Assign(Expression.ArrayAccess(newInstance, loopRankIndex), tmpValue)); } else { loopExpressions.Add(Expression.Assign(Expression.ArrayAccess(indices, Expression.Constant(loopRank)), loopRankIndex)); loopExpressions.Add(innerExpr); loopExpressions.Add(Expression.Call(newInstance, ArrayMih.SetValueRank(), Expression.Convert(tmpValue, typeof(object)), indices)); } loopExpressions.Add(Expression.Assign(loopRankIndex, Expression.Add(loopRankIndex, Expression.Constant(1)))); var cond = Expression.LessThan(loopRankIndex, Expression.ArrayIndex(lengths, Expression.Constant(loopRank))); var loopBody = Expression.Block(loopExpressions); var breakLabel = Expression.Label("breakLabel" + loopRank); var loop = Expression.Loop(Expression.IfThenElse(cond, loopBody, Expression.Break(breakLabel)), breakLabel); return(Expression.Block(Expression.Assign(loopRankIndex, Expression.Constant(0)), loop)); }; for (int r = rank - 1; r >= 0; r--) { innerExpression = readArrayLoop(r, innerExpression); } expressions.Add(innerExpression); return(expressions); }