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