Example #1
0
        /// <summary>
        /// Provides the actual implementation for serializing a value of type <see cref="T" />.
        /// </summary>
        /// <param name="value">The value to serialize.</param>
        /// <param name="writer">The writer to serialize with.</param>
        protected override void SerializeImplementation(ref T value, IDataWriter writer)
        {
            var members = FormatterUtilities.GetSerializableMembers(typeof(T), this.OverridePolicy ?? writer.Context.Config.SerializationPolicy);

            for (int i = 0; i < members.Length; i++)
            {
                var  member = members[i];
                Type type;
                var  memberValue = FormatterUtilities.GetMemberValue(member, value);

                if (object.ReferenceEquals(memberValue, null))
                {
                    type = FormatterUtilities.GetContainedType(member);
                }
                else
                {
                    type = memberValue.GetType();
                }

                var serializer = Serializer.Get(type);

                try
                {
                    serializer.WriteValueWeak(member.Name, memberValue, writer);
                }
                catch (Exception ex)
                {
                    writer.Context.Config.DebugContext.LogException(ex);
                }
            }
        }
        private static IFormatter CreateGenericFormatter(Type formattedType, ModuleBuilder moduleBuilder, ISerializationPolicy policy)
        {
            MemberInfo[] members = FormatterUtilities.GetSerializableMembers(formattedType, policy);
            Dictionary <string, MemberInfo> serializableMembers = FormatterUtilities.GetSerializableMembersMap(formattedType, policy);

            if (serializableMembers.Count == 0)
            {
                return((IFormatter)Activator.CreateInstance(typeof(EmptyTypeFormatter <>).MakeGenericType(formattedType)));
            }

            string helperTypeName = moduleBuilder.Name + "." + formattedType.GetCompilableNiceFullName() + "___" + formattedType.Assembly.GetName().Name + "___FormatterHelper___" + Guid.NewGuid().ToString();

            Dictionary <Type, MethodInfo>   serializerReadMethods;
            Dictionary <Type, MethodInfo>   serializerWriteMethods;
            Dictionary <Type, FieldBuilder> serializerFields;
            FieldBuilder dictField;
            Dictionary <MemberInfo, List <string> > memberNames;

            BuildHelperType(
                moduleBuilder,
                helperTypeName,
                formattedType,
                serializableMembers,
                out serializerReadMethods,
                out serializerWriteMethods,
                out serializerFields,
                out dictField,
                out memberNames
                );

            Type     formatterType = typeof(RuntimeEmittedFormatter <>).MakeGenericType(formattedType);
            Delegate del1, del2;

            // Read
            {
                Type          readDelegateType    = typeof(ReadDataEntryMethodDelegate <>).MakeGenericType(formattedType);
                MethodInfo    readDataEntryMethod = formatterType.GetMethod("ReadDataEntry", Flags.InstanceAnyVisibility);
                DynamicMethod dynamicReadMethod   = new DynamicMethod("Dynamic_" + formattedType.GetCompilableNiceFullName(), null, readDataEntryMethod.GetParameters().Select(n => n.ParameterType).ToArray(), true);
                readDataEntryMethod.GetParameters().ForEach(n => dynamicReadMethod.DefineParameter(n.Position, n.Attributes, n.Name));
                EmitReadMethodContents(dynamicReadMethod.GetILGenerator(), formattedType, dictField, serializerFields, memberNames, serializerReadMethods);
                del1 = dynamicReadMethod.CreateDelegate(readDelegateType);
            }

            // Write
            {
                Type          writeDelegateType      = typeof(WriteDataEntriesMethodDelegate <>).MakeGenericType(formattedType);
                MethodInfo    writeDataEntriesMethod = formatterType.GetMethod("WriteDataEntries", Flags.InstanceAnyVisibility);
                DynamicMethod dynamicWriteMethod     = new DynamicMethod("Dynamic_Write_" + formattedType.GetCompilableNiceFullName(), null, writeDataEntriesMethod.GetParameters().Select(n => n.ParameterType).ToArray(), true);
                writeDataEntriesMethod.GetParameters().ForEach(n => dynamicWriteMethod.DefineParameter(n.Position + 1, n.Attributes, n.Name));
                EmitWriteMethodContents(dynamicWriteMethod.GetILGenerator(), formattedType, members, serializerFields, memberNames, serializerWriteMethods);
                del2 = dynamicWriteMethod.CreateDelegate(writeDelegateType);
            }

            return((IFormatter)Activator.CreateInstance(formatterType, del1, del2));
        }
        /// <summary>
        /// Emits a formatter for a given type into a given module builder, using a given serialization policy to determine which members to serialize.
        /// </summary>
        /// <param name="formattedType">Type to create a formatter for.</param>
        /// <param name="moduleBuilder">The module builder to emit a formatter into.</param>
        /// <param name="policy">The serialization policy to use for creating the formatter.</param>
        /// <returns>The fully constructed, emitted formatter type.</returns>
        public static Type EmitAOTFormatter(Type formattedType, ModuleBuilder moduleBuilder, ISerializationPolicy policy)
        {
            MemberInfo[] members = FormatterUtilities.GetSerializableMembers(formattedType, policy);
            Dictionary <string, MemberInfo> serializableMembers = FormatterUtilities.GetSerializableMembersMap(formattedType, policy);

            string formatterName       = moduleBuilder.Name + "." + formattedType.GetCompilableNiceFullName() + "__AOTFormatter";
            string formatterHelperName = moduleBuilder.Name + "." + formattedType.GetCompilableNiceFullName() + "__FormatterHelper";

            if (serializableMembers.Count == 0)
            {
                return(moduleBuilder.DefineType(
                           formatterName,
                           TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.Class,
                           typeof(EmptyAOTEmittedFormatter <>).MakeGenericType(formattedType)
                           ).CreateType());
            }

            Dictionary <Type, MethodInfo>   serializerReadMethods;
            Dictionary <Type, MethodInfo>   serializerWriteMethods;
            Dictionary <Type, FieldBuilder> serializerFields;
            FieldBuilder dictField;
            Dictionary <MemberInfo, List <string> > memberNames;

            BuildHelperType(
                moduleBuilder,
                formatterHelperName,
                formattedType,
                serializableMembers,
                out serializerReadMethods,
                out serializerWriteMethods,
                out serializerFields,
                out dictField,
                out memberNames
                );

            TypeBuilder formatterType = moduleBuilder.DefineType(
                formatterName,
                TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.Class,
                typeof(AOTEmittedFormatter <>).MakeGenericType(formattedType)
                );

            // Read
            {
                MethodInfo readBaseMethod = formatterType.BaseType.GetMethod("ReadDataEntry", Flags.InstanceAnyVisibility);

                MethodBuilder readMethod = formatterType.DefineMethod(
                    readBaseMethod.Name,
                    MethodAttributes.Family | MethodAttributes.Virtual,
                    readBaseMethod.ReturnType,
                    readBaseMethod.GetParameters().Select(n => n.ParameterType).ToArray()
                    );

                readBaseMethod.GetParameters().ForEach(n => readMethod.DefineParameter(n.Position, n.Attributes, n.Name));
                EmitReadMethodContents(readMethod.GetILGenerator(), formattedType, dictField, serializerFields, memberNames, serializerReadMethods);
            }

            // Write
            {
                MethodInfo writeBaseMethod = formatterType.BaseType.GetMethod("WriteDataEntries", Flags.InstanceAnyVisibility);

                MethodBuilder dynamicWriteMethod = formatterType.DefineMethod(
                    writeBaseMethod.Name,
                    MethodAttributes.Family | MethodAttributes.Virtual,
                    writeBaseMethod.ReturnType,
                    writeBaseMethod.GetParameters().Select(n => n.ParameterType).ToArray()
                    );

                writeBaseMethod.GetParameters().ForEach(n => dynamicWriteMethod.DefineParameter(n.Position + 1, n.Attributes, n.Name));
                EmitWriteMethodContents(dynamicWriteMethod.GetILGenerator(), formattedType, members, serializerFields, memberNames, serializerWriteMethods);
            }

            var result = formatterType.CreateType();

            // Register the formatter on the assembly
            ((AssemblyBuilder)moduleBuilder.Assembly).SetCustomAttribute(new CustomAttributeBuilder(typeof(RegisterFormatterAttribute).GetConstructor(new Type[] { typeof(Type), typeof(int) }), new object[] { formatterType, -1 }));

            return(result);
        }
Example #4
0
        private static void ReplaceAllReferencesInGraph(object graph, object oldReference, object newReference, HashSet <object> processedReferences = null)
        {
            if (processedReferences == null)
            {
                processedReferences = new HashSet <object>(ReferenceEqualityComparer <object> .Default);
            }

            processedReferences.Add(graph);

            if (graph.GetType().IsArray)
            {
                Array array = (Array)graph;

                for (int i = 0; i < array.Length; i++)
                {
                    var value = array.GetValue(i);

                    if (object.ReferenceEquals(value, null))
                    {
                        continue;
                    }

                    if (object.ReferenceEquals(value, oldReference))
                    {
                        array.SetValue(newReference, i);
                        value = newReference;
                    }

                    if (!processedReferences.Contains(value))
                    {
                        ReplaceAllReferencesInGraph(value, oldReference, newReference, processedReferences);
                    }
                }
            }
            else
            {
                var members = FormatterUtilities.GetSerializableMembers(graph.GetType(), SerializationPolicies.Everything);

                for (int i = 0; i < members.Length; i++)
                {
                    FieldInfo field = (FieldInfo)members[i];

                    if (field.FieldType.IsPrimitive || field.FieldType == typeof(SerializationData) || field.FieldType == typeof(string))
                    {
                        continue;
                    }

                    object value = field.GetValue(graph);

                    if (object.ReferenceEquals(value, null))
                    {
                        continue;
                    }

                    Type valueType = value.GetType();

                    if (valueType.IsPrimitive || valueType == typeof(SerializationData) || valueType == typeof(string))
                    {
                        continue;
                    }

                    if (object.ReferenceEquals(value, oldReference))
                    {
                        field.SetValue(graph, newReference);
                        value = newReference;
                    }

                    if (!processedReferences.Contains(value))
                    {
                        ReplaceAllReferencesInGraph(value, oldReference, newReference, processedReferences);
                    }
                }
            }
        }