/// <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 that call the clone implementation method /// </summary> /// <param name="source">Source object</param> /// <param name="refTrackerParam">Reference tracker</param> /// <param name="expectedType">Expected type....mostly used for IQueryable detection</param> /// <returns>An expression that call the clone implementation method</returns> internal static Expression CallCopyExpression(Expression source, ParameterExpression refTrackerParam, Expression expectedType) { var itemAsObject = Expression.Parameter(typeof(object), "itemAsObject"); var variables = new List <ParameterExpression>(); variables.Add(itemAsObject); var expressions = new List <Expression>(); expressions.Add(Expression.Assign(itemAsObject, Expression.Call(SerializerMih.PrepareObjectForSerialization(), source))); expressions.Add(Expression.Assign(itemAsObject, Expression.Call(Expression.Call(ObjectClonerMih.CloneImpl(), Expression.Call(itemAsObject, ObjectMih.GetTypeMethod())), FuncMih.CloneMethodInvoke(), Expression.Convert(itemAsObject, typeof(object)), refTrackerParam))); expressions.Add(Expression.Call(SerializerMih.ConvertObjectToExpectedType(), itemAsObject, expectedType)); return(Expression.Block(variables, expressions)); }
/// <summary> /// Generates an expression tree to handle class type serialization /// </summary> /// <param name="outputStream">Stream to write to</param> /// <param name="objTracking">Reference tracker</param> /// <param name="item">Source object</param> /// <param name="itemAsObj">Source object as an object</param> /// <param name="typeExpr">Type of the object as an expression</param> /// <param name="serializer">Serializer temporary variable</param> /// <param name="itemType">Type of the element</param> /// <returns>An expression tree to handle class type serialization</returns> internal static Expression GetWriteClassTypeExpression(ParameterExpression outputStream, ParameterExpression objTracking, Expression item, Expression itemAsObj, ParameterExpression typeExpr, ParameterExpression serializer, Type itemType) { var writeType = Expression.IfThenElse(Expression.Equal(Expression.Call(item, ObjectMih.GetTypeMethod()), Expression.Constant(itemType)), Expression.Block(PrimitiveHelpers.WriteByte(outputStream, Expression.Constant(SerializerObjectTracker.Value0), objTracking), Expression.Assign(typeExpr, Expression.Constant(itemType)), Expression.Assign(itemAsObj, Expression.Convert(item, typeof(object)))), Expression.Block(PrimitiveHelpers.WriteByte(outputStream, Expression.Constant(SerializerObjectTracker.Value1), objTracking), Expression.Assign(itemAsObj, Expression.Call(SerializerMih.PrepareObjectForSerialization(), item)), Expression.Assign(typeExpr, Expression.Call(itemAsObj, ObjectMih.GetTypeMethod())), GenerateStringExpression(outputStream, Expression.Call(SerializedTypeResolverMih.GetShortNameFromType(), typeExpr), objTracking), PrimitiveHelpers.WriteInt32(outputStream, Expression.Call(SerializedTypeResolverMih.GetHashCodeFromType(), typeExpr), objTracking))); return(Expression.IfThenElse(Expression.Equal(item, Expression.Constant(null)), PrimitiveHelpers.WriteByte(outputStream, Expression.Constant(SerializerObjectTracker.Value0), objTracking), Expression.Block(PrimitiveHelpers.WriteByte(outputStream, Expression.Constant(SerializerObjectTracker.Value1), objTracking), writeType, Expression.Assign(serializer, Expression.Call(SerializerMih.GetTypeToObjectSerializer(), typeExpr)), Expression.Invoke(serializer, outputStream, itemAsObj, objTracking)))); }
internal static void GenerateCopyFieldsExpressions(IEnumerable <FieldInfo> fields, ParameterExpression source, ParameterExpression clone, List <Expression> expressions, ParameterExpression refTrackerParam, ParameterExpression clonedItem) { foreach (var field in fields) { var cloneField = Expression.Field(clone, field); var sourceField = Expression.Field(source, field); if (field.FieldType.IsPrimitive || field.FieldType.IsValueType || (field.FieldType == typeof(string))) { if (field.IsInitOnly) { expressions.Add(Expression.Call(CopyReadOnlyFieldMethodInfo.GetMethodInfo(), Expression.Constant(field), Expression.Convert(sourceField, typeof(object)), clone)); } else { var from = sourceField; var to = cloneField; expressions.Add(Expression.Assign(to, from)); } } else { var es = new List <Expression>(); es.Add(Expression.Assign(clonedItem, Expression.Call(SerializerMih.PrepareObjectForSerialization(), sourceField))); es.Add(Expression.Assign(clonedItem, CallCopyExpression(clonedItem, refTrackerParam, Expression.Constant(field.FieldType)))); if (IQueryableCloner.IsGenericIQueryableType(field.FieldType)) { Type queryableInterface = IQueryableCloner.GetInterfaceType(field.FieldType, typeof(IQueryable <>)); var genericArgumentType = queryableInterface.GetGenericArguments()[0]; var copy2 = Expression.Convert(clonedItem, field.FieldType); var m = Expression.Call(typeof(Queryable), "AsQueryable", new Type[] { genericArgumentType }, Expression.Convert(copy2, typeof(IEnumerable <>).MakeGenericType(genericArgumentType))); es.Add(Expression.Assign(clonedItem, m)); } if (field.FieldType == typeof(IQueryable)) { es.Add(Expression.Assign(clonedItem, Expression.Call(IQueryableMih.ConvertToNonGenericQueryable(), clonedItem))); } if (field.IsInitOnly) { Func <Expression, Expression> assignExpr = exx => Expression.Call(CopyReadOnlyFieldMethodInfo.GetMethodInfo(), Expression.Constant(field), Expression.Convert(exx, typeof(object)), clone); var assignNullExpr = Expression.Call(CopyReadOnlyFieldMethodInfo.GetMethodInfo(), Expression.Constant(field), Expression.Constant(null, typeof(object)), clone); es.Add(clonedItem); var conditionalExpression = Expression.IfThenElse(Expression.NotEqual(sourceField, Expression.Constant(null)), assignExpr(Expression.Block(es)), assignNullExpr); expressions.Add(ObjectCloner.GenerateNullTrackedOrUntrackedExpression(sourceField, cloneField, field.FieldType, refTrackerParam, conditionalExpression, trackedExpression: assignExpr)); // todo refactor this horrible method } else { es.Add(Expression.Assign(cloneField, Expression.Convert(clonedItem, field.FieldType))); var conditionalExpression = Expression.IfThenElse(Expression.Equal(sourceField, Expression.Constant(null)), Expression.Assign(cloneField, Expression.Constant(null, field.FieldType)), Expression.Block(es)); expressions.Add(ObjectCloner.GenerateNullTrackedOrUntrackedExpression(sourceField, cloneField, field.FieldType, refTrackerParam, conditionalExpression)); } } } }