/// <summary> /// Generates an expression tree to handle jagged array deserialization /// </summary> /// <param name="type">Type of array</param> /// <param name="inputStream">Stream to read from</param> /// <param name="objTracking">Reference tracker</param> /// <returns>An expression tree to handle jagged array deserialization</returns> public static Expression GenerateJaggedArray(Type type, ParameterExpression inputStream, ParameterExpression objTracking) { List <ParameterExpression> variables = new List <ParameterExpression>(); var elementType = type.GetElementType(); var trackType = Expression.Parameter(typeof(byte), "trackType"); var newInstance = Expression.Parameter(type, "newInstance"); var numberOfDimensions = Expression.Parameter(typeof(int), "numberOfDimensions"); var lengths = Expression.Parameter(typeof(int[]), "lengths"); var item = Expression.Parameter(type.GetElementType(), "item"); variables.Add(trackType); variables.Add(newInstance); variables.Add(lengths); variables.Add(item); variables.Add(numberOfDimensions); List <Expression> notTrackedExpressions = new List <Expression>(); notTrackedExpressions.AddRange(ReadJaggedArray(type, elementType, newInstance, variables, inputStream, objTracking)); return(Deserializer.GenerateNullTrackedOrUntrackedExpression(type, inputStream, objTracking, newInstance, notTrackedExpressions, trackType, variables)); }
/// <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> /// Generate an expression tree to handle array deserialization /// </summary> /// <param name="type">Type of the array</param> /// <param name="inputStream">Stream that is read from</param> /// <param name="objTracker">Reference tracker</param> /// <returns>An expression tree to handle array deserialization</returns> internal static Expression GenerateArrayOfKnownDimension(Type type, ParameterExpression inputStream, ParameterExpression objTracker) { List <ParameterExpression> variables = new List <ParameterExpression>(); var elementType = type.GetElementType(); var trackType = Expression.Parameter(typeof(byte), "trackType"); var newInstance = Expression.Parameter(type, "newInstance"); var i = Expression.Parameter(typeof(int), "i"); var numberOfDimensions = Expression.Parameter(typeof(int), "numberOfDimensions"); var lengths = Expression.Parameter(typeof(int[]), "lengths"); var item = Expression.Parameter(type.GetElementType(), "item"); variables.Add(trackType); variables.Add(newInstance); variables.Add(i); variables.Add(lengths); variables.Add(item); variables.Add(numberOfDimensions); var rank = type.GetArrayRank(); List <Expression> notTrackedExpressions = new List <Expression>(); notTrackedExpressions.AddRange(ReadDimensionalArrayLength(inputStream, objTracker, lengths, i, numberOfDimensions)); notTrackedExpressions.AddRange(ReadDimensionalArray(type, elementType, newInstance, variables, inputStream, lengths, objTracker, rank)); 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)); }
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)); }
/// <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)); }
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)); }