private static Expression SerializeDictionaryWithDefaultComparer(Type genericDictionaryType, List <ParameterExpression> variables, Type type, ParameterExpression outputStream, ParameterExpression objToSerialize, ParameterExpression objTracking) { List <Expression> notTrackedExpressions = new List <Expression>(); notTrackedExpressions.Add(PrimitiveHelpers.WriteByte(outputStream, Expression.Constant(SerializerObjectTracker.Value0, typeof(byte)), objTracking)); var fields = InternalSerializationStuff.GetFields(type, genericDictionaryType); Serializer.GenerateFieldsExpression(type, fields, outputStream, objToSerialize, objTracking, variables, notTrackedExpressions); notTrackedExpressions.Add(SerializeDictionary(type, genericDictionaryType, variables, outputStream, objToSerialize, objTracking, false)); return(Expression.Block(notTrackedExpressions)); }
/// <summary> /// Generate an expression tree to clone a class /// </summary> /// <param name="variables">Global variables for the expression tree</param> /// <param name="sourceType">Type of the source object</param> /// <param name="source">Source object</param> /// <param name="clone">Clone object</param> /// <param name="refTrackerParam">Reference tracker</param> /// <returns>An expression tree that can clone a class</returns> internal static Expression GenerateClassExpressions(List <ParameterExpression> variables, Type sourceType, ParameterExpression source, ParameterExpression clone, ParameterExpression refTrackerParam) { var cloner = Expression.Parameter(typeof(Func <object, ObjectClonerReferenceTracker, object>), "cloner"); var clonedItem = Expression.Parameter(typeof(object), "clonedItem"); variables.Add(cloner); variables.Add(clonedItem); var ctor = Expression.Call(FormatterServicesMih.GetUninitializedObject(), Expression.Constant(sourceType)); var copyExpressions = new List <Expression>(); var fields = InternalSerializationStuff.GetFields(sourceType); copyExpressions.Add(Expression.Assign(clone, Expression.Convert(ctor, sourceType))); copyExpressions.Add(Expression.Call(refTrackerParam, ObjectClonerReferenceTrackerMih.Track(), source, clone)); GenerateCopyFieldsExpressions(fields, source, clone, copyExpressions, refTrackerParam, clonedItem); return(ObjectCloner.GenerateNullTrackedOrUntrackedExpression(source, clone, sourceType, refTrackerParam, Expression.Block(copyExpressions))); }
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 Func <object, ObjectClonerReferenceTracker, object> GenerateCloner(Type sourceType) { InternalSerializationStuff.ValidateSupportedTypes(sourceType); ParameterExpression sourceParameter = Expression.Parameter(typeof(object), "sourceParam"); ParameterExpression refTrackerParam = Expression.Parameter(typeof(ObjectClonerReferenceTracker), "refTrackerParam"); var clone = Expression.Parameter(sourceType, "newInstance"); var source = Expression.Parameter(sourceType, "source"); var variables = new List <ParameterExpression>(); var expressions = new List <Expression>(); variables.Add(source); variables.Add(clone); expressions.Add(Expression.Assign(source, Expression.Convert(sourceParameter, sourceType))); if (sourceType.IsPrimitive || sourceType.IsValueType || (sourceType == typeof(string))) { expressions.Add(Expression.Assign(clone, source)); } else if (InternalSerializationStuff.ImplementsISerializableWithSerializationConstructor(sourceType)) { expressions.Add(ISerializableCloner.GenerateISerializableExpression(variables, source, clone, sourceType, refTrackerParam)); } else if (InternalSerializationStuff.ImplementsDictionaryGeneric(sourceType)) { expressions.Add(DictionaryCloner.GenerateDictionaryGenericExpression(variables, source, clone, sourceType, refTrackerParam)); } else if (sourceType == typeof(ExpandoObject)) { expressions.Add(ExpandoCloner.GenerateExpandoObjectExpression(variables, source, clone, refTrackerParam)); } else if (sourceType.IsArray) { expressions.Add(ArrayCloner.GenerateArrayExpression(variables, source, clone, sourceType, refTrackerParam)); } else { expressions.Add(ClassCloner.GenerateClassExpressions(variables, sourceType, source, clone, refTrackerParam)); } // Value types require manual boxing if (sourceType.IsValueType) { expressions.Add(Expression.Convert(clone, typeof(object))); } else { expressions.Add(clone); } return(Expression.Lambda <Func <object, ObjectClonerReferenceTracker, object> >(Expression.Block(variables, expressions), sourceParameter, refTrackerParam).Compile()); }
public void GetFieldShouldExcludeSpecifiedBaseClass() { var fields = InternalSerializationStuff.GetFields(typeof(CustomDictionaryWithAdditionalPropertiesWithoutOverridingOnDeserializedCallback), typeof(Dictionary <string, object>)); fields.Select(x => x.Name) .ToArray() .Should() .BeEquivalentTo(new[] { "<SomeProperty>k__BackingField" }); }
private static Expression SerializeDictionaryWithCustomComparer(Type genericDictionaryType, List <ParameterExpression> variables, Type type, ParameterExpression outputStream, ParameterExpression objToSerialize, ParameterExpression objTracking) { var serializer = Expression.Parameter(typeof(Action <Stream, object, SerializerObjectTracker>), "serializer"); var typeExpr = Expression.Parameter(typeof(Type), "typeExpr"); var itemAsObj = Expression.Parameter(typeof(object), "itemAsObj"); variables.Add(serializer); variables.Add(typeExpr); variables.Add(itemAsObj); List <Expression> notTrackedExpressions = new List <Expression>(); notTrackedExpressions.Add(PrimitiveHelpers.WriteByte(outputStream, Expression.Constant(SerializerObjectTracker.Value1, typeof(byte)), objTracking)); var comparerProperty = Expression.Property(objToSerialize, nameof(Dictionary <int, int> .Comparer)); notTrackedExpressions.Add(Serializer.GetWriteClassTypeExpression(outputStream, objTracking, comparerProperty, itemAsObj, typeExpr, serializer, typeof(object))); var fields = InternalSerializationStuff.GetFields(type, genericDictionaryType); Serializer.GenerateFieldsExpression(type, fields, outputStream, objToSerialize, objTracking, variables, notTrackedExpressions); notTrackedExpressions.Add(SerializeDictionary(type, genericDictionaryType, variables, outputStream, objToSerialize, objTracking, false)); return(Expression.Block(notTrackedExpressions)); }
private static System.Delegate CreateTypeSerializer(Type type) { InternalSerializationStuff.ValidateSupportedTypes(type); var variables = new List <ParameterExpression>(); var expressions = new List <Expression>(); var outputStream = Expression.Parameter(typeof(Stream), "outputStream"); var objToSerialize = Expression.Parameter(type, "objToSerialize"); var objTracking = Expression.Parameter(typeof(SerializerObjectTracker), "objTracking"); var primitiveWriter = GetPrimitiveWriter(type); if (primitiveWriter != null) { Debug.Assert(type.IsPrimitive || type.IsValueType, "Value is not a primitive"); expressions.Add(primitiveWriter(outputStream, objToSerialize, objTracking)); } else if (type == typeof(string)) { expressions.Add(GenerateStringExpression(outputStream, objToSerialize, objTracking)); } else if (InternalSerializationStuff.ImplementsISerializableWithSerializationConstructor(type)) { expressions.Add(ISerializableSerializer.GenerateISerializableExpression(type, variables, outputStream, objToSerialize, objTracking)); } else if (InternalSerializationStuff.ImplementsDictionaryGeneric(type)) { expressions.Add(DictionarySerializer.GenerateDictionaryGenericExpression(type, variables, outputStream, objToSerialize, objTracking)); } else if (type == typeof(ExpandoObject)) { expressions.Add(ExpandoSerializer.GenerateExpandoObjectExpression(type, variables, outputStream, objToSerialize, objTracking)); } else if (type.IsArray) { expressions.Add(GenerateArrayExpression(type, outputStream, objToSerialize, objTracking)); } else { expressions.Add(GenerateClassExpression(type, outputStream, objToSerialize, objTracking)); } var block = Expression.Block(variables, expressions); var a = typeof(Action <, ,>).MakeGenericType(typeof(Stream), type, typeof(SerializerObjectTracker)); return(Expression.Lambda(a, block, outputStream, objToSerialize, objTracking).Compile()); }
private static System.Delegate CreateTypeDeserializer(Type type) { var expressions = new List <Expression>(); var variables = new List <ParameterExpression>(); var inputStream = Expression.Parameter(typeof(Stream), "inputStream"); var objTracker = Expression.Parameter(typeof(DeserializerObjectTracker), "objTracker"); var returnValue = Expression.Parameter(type, "retVal"); variables.Add(returnValue); var primitiveReader = GetPrimitiveReader(type); if (primitiveReader != null) { expressions.Add(Expression.Assign(returnValue, Expression.Convert(primitiveReader(inputStream, objTracker), type))); } else if (type == typeof(string)) { expressions.Add(Expression.Assign(returnValue, GenerateStringExpression(inputStream, objTracker))); } else if (InternalSerializationStuff.ImplementsISerializableWithSerializationConstructor(type)) { expressions.Add(Expression.Assign(returnValue, ISerializableDeserializer.GenerateISerializableExpression(type, variables, inputStream, objTracker))); } else if (InternalSerializationStuff.ImplementsDictionaryGeneric(type)) { expressions.Add(Expression.Assign(returnValue, DictionaryDeserializer.GenerateDictionaryGenericExpression(type, variables, inputStream, objTracker))); } else if (type.IsArray) { expressions.Add(Expression.Assign(returnValue, GenerateArrayExpression(type, inputStream, objTracker))); } else if (type == typeof(ExpandoObject)) { expressions.Add(Expression.Assign(returnValue, ExpandoDeserializer.GenerateExpandoObjectExpression(variables, inputStream, objTracker))); } else { expressions.Add(Expression.Assign(returnValue, GenerateClassExpression(type, inputStream, objTracker))); } expressions.Add(returnValue); var block = Expression.Block(variables, expressions); var f = typeof(Func <, ,>).MakeGenericType(typeof(Stream), typeof(DeserializerObjectTracker), type); return(Expression.Lambda(f, block, inputStream, objTracker).Compile()); }
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)); }
public void GetFieldsShouldIncludeBaseClass() { var fields = InternalSerializationStuff.GetFields(typeof(CustomDictionaryWithAdditionalPropertiesWithoutOverridingOnDeserializedCallback)); fields.Select(x => x.Name) .ToArray() .Should() .BeEquivalentTo(new[] { "<SomeProperty>k__BackingField", "_syncRoot", "buckets", "comparer", "count", "entries", "freeCount", "freeList", "keys", "values", "version" }); }
/// <summary> /// Generate an epxression tree to handle class serialization /// </summary> /// <param name="type">Type to serialize</param> /// <param name="outputStream">Stream to write to</param> /// <param name="objToSerialize">Object to serialize</param> /// <param name="objTracking">Reference tracker</param> /// <returns>An epxression tree to handle class serialization</returns> internal static Expression GenerateClassExpression(Type type, ParameterExpression outputStream, Expression objToSerialize, ParameterExpression objTracking) { List <Expression> notTrackedExpressions = new List <Expression>(); List <ParameterExpression> variables = new List <ParameterExpression>(); GenerateFieldsExpression(type, InternalSerializationStuff.GetFields(type), outputStream, objToSerialize, objTracking, variables, notTrackedExpressions); return(GenerateNullTrackedOrUntrackedExpression(type, outputStream, objToSerialize, objTracking, notTrackedExpressions, variables)); }
private static void CopyFieldsAndValues(Type genericDictionaryType, ParameterExpression source, ParameterExpression clone, Type sourceType, ParameterExpression refTrackerParam, List <Expression> expressions, List <ParameterExpression> variables) { var clonedItem = Expression.Parameter(typeof(object), "clonedItem"); variables.Add(clonedItem); var fields = InternalSerializationStuff.GetFields(sourceType, genericDictionaryType); ClassCloner.GenerateCopyFieldsExpressions(fields, source, clone, expressions, refTrackerParam, clonedItem); var typeKey = genericDictionaryType.GenericTypeArguments[0]; var typeValue = genericDictionaryType.GenericTypeArguments[1]; if (IsPrimitive(typeKey) && IsPrimitive(typeValue)) { expressions.Add(Expression.Call(typeof(DictionaryCloner), nameof(DictionaryCloner.CopyPrimitiveKeyAndPrimitiveValue), genericDictionaryType.GenericTypeArguments, source, clone)); } else if (!IsPrimitive(typeKey) && IsPrimitive(typeValue)) { expressions.Add(Expression.Call(typeof(DictionaryCloner), nameof(DictionaryCloner.CopyObjectKeyAndPrimitiveValue), genericDictionaryType.GenericTypeArguments, source, clone, refTrackerParam)); } else if (IsPrimitive(typeKey) && !IsPrimitive(typeValue)) { expressions.Add(Expression.Call(typeof(DictionaryCloner), nameof(DictionaryCloner.CopyPrivitiveKeyAndObjectValue), genericDictionaryType.GenericTypeArguments, source, clone, refTrackerParam)); } else { expressions.Add(Expression.Call(typeof(DictionaryCloner), nameof(DictionaryCloner.CopyObjectKeyAndObjectValue), genericDictionaryType.GenericTypeArguments, source, clone, refTrackerParam)); } }