private IlDelegateBuilder <SerializationManager.Serializer> EmitSerializer(Type type, List <FieldInfo> fields)
        {
            var builder = new IlDelegateBuilder <SerializationManager.Serializer>(
                type.Name + "Serializer",
                this.methods,
                this.methods.SerializerDelegate);

            // Declare local variables.
            var typedInput = builder.DeclareLocal(type);

            // Set the typed input variable from the method parameter.
            builder.LoadArgument(0);
            builder.CastOrUnbox(type);
            builder.StoreLocal(typedInput);

            // Serialize each field
            foreach (var field in fields)
            {
                // Load the field.
                builder.LoadLocal(typedInput);
                builder.LoadField(field);
                builder.BoxIfValueType(field.FieldType);

                // Serialize the field.
                builder.LoadArgument(1);
                builder.LoadType(field.FieldType);
                builder.Call(this.methods.SerializeInner);
            }

            builder.Return();
            return(builder);
        }
        private IlDelegateBuilder <SerializationManager.DeepCopier> EmitCopier(Type type, List <FieldInfo> fields)
        {
            var builder = new IlDelegateBuilder <SerializationManager.DeepCopier>(
                type.Name + "DeepCopier",
                this.methods,
                this.methods.DeepCopierDelegate);

            // Declare local variables.
            var result     = builder.DeclareLocal(type);
            var typedInput = builder.DeclareLocal(type);

            // Set the typed input variable from the method parameter.
            builder.LoadArgument(0);
            builder.CastOrUnbox(type);
            builder.StoreLocal(typedInput);

            // Construct the result.
            builder.CreateInstance(type, result);

            // Record the object.
            builder.Call(this.methods.GetCurrentSerializationContext);
            builder.LoadArgument(0);   // Load 'original' parameter.
            builder.LoadLocal(result); // Load 'result' local.
            builder.BoxIfValueType(type);
            builder.Call(this.methods.RecordObjectWhileCopying);

            // Copy each field.
            foreach (var field in fields)
            {
                // Load the field.
                builder.LoadLocalAsReference(type, result);
                builder.LoadLocal(typedInput);
                builder.LoadField(field);

                // Deep-copy the field if needed, otherwise just leave it as-is.
                if (!field.FieldType.IsOrleansShallowCopyable())
                {
                    builder.BoxIfValueType(field.FieldType);
                    builder.Call(this.methods.DeepCopyInner);
                    builder.CastOrUnbox(field.FieldType);
                }

                // Store the copy of the field on the result.
                builder.StoreField(field);
            }

            builder.LoadLocal(result);
            builder.BoxIfValueType(type);
            builder.Return();
            return(builder);
        }
        private IlDelegateBuilder <SerializationManager.Deserializer> EmitDeserializer(Type type, List <FieldInfo> fields)
        {
            var builder = new IlDelegateBuilder <SerializationManager.Deserializer>(
                type.Name + "Deserializer",
                this.methods,
                this.methods.DeserializerDelegate);

            // Declare local variables.
            var result = builder.DeclareLocal(type);

            // Construct the result.
            builder.CreateInstance(type, result);

            // Record the object.
            builder.Call(this.methods.GetCurrentDeserializationContext);
            builder.LoadLocal(result);
            builder.BoxIfValueType(type);
            builder.Call(this.methods.RecordObjectWhileDeserializing);

            // Deserialize each field.
            foreach (var field in fields)
            {
                // Deserialize the field.
                builder.LoadLocalAsReference(type, result);
                builder.LoadType(field.FieldType);
                builder.LoadArgument(1);
                builder.Call(this.methods.DeserializeInner);

                // Store the value on the result.
                builder.CastOrUnbox(field.FieldType);
                builder.StoreField(field);
            }

            builder.LoadLocal(result);
            builder.BoxIfValueType(type);
            builder.Return();
            return(builder);
        }