Index: /branches/PersistenceReintegration/HeuristicLab.ExtLibs/HeuristicLab.ProtobufCS/3.5.0/HeuristicLab.ProtobufCS/HeuristicLab.Protobuf-3.5.0.csproj
===================================================================
--- /branches/PersistenceReintegration/HeuristicLab.ExtLibs/HeuristicLab.ProtobufCS/3.5.0/HeuristicLab.ProtobufCS/HeuristicLab.Protobuf-3.5.0.csproj	(revision 15528)
+++ /branches/PersistenceReintegration/HeuristicLab.ExtLibs/HeuristicLab.ProtobufCS/3.5.0/HeuristicLab.ProtobufCS/HeuristicLab.Protobuf-3.5.0.csproj	(revision 15529)
@@ -76,3 +76,12 @@
     <PostBuildEvent>copy "$(ProjectDir)protoc-3.5.0.exe" "$(SolutionDir)"</PostBuildEvent>
   </PropertyGroup>
+  <PropertyGroup>
+    <PreBuildEvent>set Path=%25Path%25;$(ProjectDir);$(SolutionDir)
+set ProjectDir=$(ProjectDir)
+set SolutionDir=$(SolutionDir)
+set Outdir=$(Outdir)
+
+call PreBuildEvent.cmd
+</PreBuildEvent>
+  </PropertyGroup>
 </Project>
Index: anches/PersistenceReintegration/HeuristicLab.ExtLibs/HeuristicLab.ProtobufCS/3.5.0/HeuristicLab.ProtobufCS/Plugin.cs
===================================================================
--- /branches/PersistenceReintegration/HeuristicLab.ExtLibs/HeuristicLab.ProtobufCS/3.5.0/HeuristicLab.ProtobufCS/Plugin.cs	(revision 15528)
+++ 	(revision )
@@ -1,31 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2016 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
- *
- * This file is part of HeuristicLab.
- *
- * HeuristicLab is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * HeuristicLab is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
- */
-#endregion
-
-using HeuristicLab.PluginInfrastructure;
-
-namespace HeuristicLab.ProtobufCS {
-  [Plugin("HeuristicLab.ProtobufCS", "2.4.1.473")]
-  [PluginFile("HeuristicLab.ProtobufCS-2.4.1.473.dll", PluginFileType.Assembly)]
-  [PluginFile("Google.ProtocolBuffers-2.4.1.473.dll", PluginFileType.Assembly)]
-  [PluginFile("Google.ProtocolBuffers-license-2.4.1.473.txt", PluginFileType.License)]
-  public class HeuristicLabProtobufCSPlugin : PluginBase {
-  }
-}
Index: /branches/PersistenceReintegration/HeuristicLab.ExtLibs/HeuristicLab.ProtobufCS/3.5.0/HeuristicLab.ProtobufCS/Plugin.cs.frame
===================================================================
--- /branches/PersistenceReintegration/HeuristicLab.ExtLibs/HeuristicLab.ProtobufCS/3.5.0/HeuristicLab.ProtobufCS/Plugin.cs.frame	(revision 15528)
+++ /branches/PersistenceReintegration/HeuristicLab.ExtLibs/HeuristicLab.ProtobufCS/3.5.0/HeuristicLab.ProtobufCS/Plugin.cs.frame	(revision 15529)
@@ -25,5 +25,5 @@
   [Plugin("HeuristicLab.ProtobufCS", "3.5.0.0")]
   [PluginFile("HeuristicLab.Protobuf-3.5.0.dll", PluginFileType.Assembly)]
-  [PluginFile("Google.ProtocolBuffers.dll", PluginFileType.Assembly)]
+  [PluginFile("Google.Protobuf.dll", PluginFileType.Assembly)]
   [PluginFile("Google.Protobuf License-3.5.0.txt", PluginFileType.License)]
   public class HeuristicLabProtobufCSPlugin : PluginBase {
Index: /branches/PersistenceReintegration/HeuristicLab.Persistence/4.0/Core/ComponentInfo.cs
===================================================================
--- /branches/PersistenceReintegration/HeuristicLab.Persistence/4.0/Core/ComponentInfo.cs	(revision 15528)
+++ /branches/PersistenceReintegration/HeuristicLab.Persistence/4.0/Core/ComponentInfo.cs	(revision 15529)
@@ -25,4 +25,5 @@
   public sealed class ComponentInfo {
     public string Name { get; private set; }
+    public string FullName { get; private set; }
     public MemberInfo MemberInfo { get; private set; }
     public StorableAttribute StorableAttribute { get; private set; }
@@ -30,6 +31,7 @@
     public bool Writeable { get; private set; }
 
-    public ComponentInfo(string name, MemberInfo memberInfo, StorableAttribute storableAttribute, bool readable, bool writeable) {
+    public ComponentInfo(string name, string fullName, MemberInfo memberInfo, StorableAttribute storableAttribute, bool readable, bool writeable) {
       Name = name;
+      FullName = fullName;
       MemberInfo = memberInfo;
       StorableAttribute = storableAttribute;
Index: /branches/PersistenceReintegration/HeuristicLab.Persistence/4.0/Core/Mapper.cs
===================================================================
--- /branches/PersistenceReintegration/HeuristicLab.Persistence/4.0/Core/Mapper.cs	(revision 15528)
+++ /branches/PersistenceReintegration/HeuristicLab.Persistence/4.0/Core/Mapper.cs	(revision 15529)
@@ -60,21 +60,7 @@
     private Dictionary<object, uint> object2BoxId;
     private Dictionary<uint, object> boxId2Object;
-    private Index<TypeBox> typeBoxes;
-
     private Index<string> strings;
 
-    private Index<BoolArrayBox> boolArrayBoxes;
-    private Index<IntArrayBox> intArrayBoxes;
-    private Index<UnsignedIntArrayBox> unsignedIntArrayBoxes;
-    private Index<LongArrayBox> longArrayBoxes;
-    private Index<UnsignedLongArrayBox> unsignedLongArrayBoxes;
-    private Index<FloatArrayBox> floatArrayBoxes;
-    private Index<DoubleArrayBox> doubleArrayBoxes;
-
-    private Index<DictionaryBox> dictionaryBoxes;
-    private Index<StorableClassBox> storableClassBoxes;
-
     public uint BoxCount { get; private set; }
-
 
     public Mapper() {
@@ -85,18 +71,5 @@
       object2BoxId = new Dictionary<object, uint>(new MappingEqualityComparer());
       boxId2Object = new Dictionary<uint, object>();
-      typeBoxes = new Index<TypeBox>();
-
       strings = new Index<string>();
-
-      boolArrayBoxes = new Index<BoolArrayBox>();
-      intArrayBoxes = new Index<IntArrayBox>();
-      unsignedIntArrayBoxes = new Index<UnsignedIntArrayBox>();
-      longArrayBoxes = new Index<LongArrayBox>();
-      unsignedLongArrayBoxes = new Index<UnsignedLongArrayBox>();
-      floatArrayBoxes = new Index<FloatArrayBox>();
-      doubleArrayBoxes = new Index<DoubleArrayBox>();
-
-      dictionaryBoxes = new Index<DictionaryBox>();
-      storableClassBoxes = new Index<StorableClassBox>();
 
       BoxCount = 0;
@@ -164,56 +137,4 @@
       return o;
     }
-
-    #region Referenced Boxes
-    #region TypeBoxes
-    public uint GetTypeBoxId(TypeBox typeBox) { return typeBoxes.GetIndex(typeBox); }
-    public TypeBox GetTypeBox(uint typeBoxId) { return typeBoxes.GetValue(typeBoxId); }
-    #endregion
-
-    #region BoolArrayBox
-    public uint GetBoolArrayBoxId(BoolArrayBox boolArrayBox) { return boolArrayBoxes.GetIndex(boolArrayBox); }
-    public BoolArrayBox GetBoolArrayBox(uint boolArrayBoxId) { return boolArrayBoxes.GetValue(boolArrayBoxId); }
-    #endregion
-
-    #region IntArrayBox
-    public uint GetIntArrayBoxId(IntArrayBox intArrayBox) { return intArrayBoxes.GetIndex(intArrayBox); }
-    public IntArrayBox GetIntArrayBox(uint intArrayBoxId) { return intArrayBoxes.GetValue(intArrayBoxId); }
-    #endregion
-
-    #region UnsignedIntArrayBox
-    public uint GetUnsignedIntArrayBoxId(UnsignedIntArrayBox unsignedIntArrayBox) { return unsignedIntArrayBoxes.GetIndex(unsignedIntArrayBox); }
-    public UnsignedIntArrayBox GetUnsignedIntArrayBox(uint unsignedIntArrayBoxId) { return unsignedIntArrayBoxes.GetValue(unsignedIntArrayBoxId); }
-    #endregion
-
-    #region LongArrayBox
-    public uint GetLongArrayBoxId(LongArrayBox longArrayBox) { return longArrayBoxes.GetIndex(longArrayBox); }
-    public LongArrayBox GetLongArrayBox(uint longArrayBoxId) { return longArrayBoxes.GetValue(longArrayBoxId); }
-    #endregion
-
-    #region UnsignedLongArrayBox
-    public uint GetUnsignedLongArrayBoxId(UnsignedLongArrayBox unsignedLongArrayBox) { return unsignedLongArrayBoxes.GetIndex(unsignedLongArrayBox); }
-    public UnsignedLongArrayBox GetUnsignedLongArrayBox(uint unsignedLongArrayBoxId) { return unsignedLongArrayBoxes.GetValue(unsignedLongArrayBoxId); }
-    #endregion
-
-    #region FloatArrayBox
-    public uint GetFloatArrayBoxId(FloatArrayBox floatArrayBox) { return floatArrayBoxes.GetIndex(floatArrayBox); }
-    public FloatArrayBox GetFloatArrayBox(uint floatArrayBoxId) { return floatArrayBoxes.GetValue(floatArrayBoxId); }
-    #endregion
-
-    #region DoubleArrayBox
-    public uint GetDoubleArrayBoxId(DoubleArrayBox doubleArrayBox) { return doubleArrayBoxes.GetIndex(doubleArrayBox); }
-    public DoubleArrayBox GetDoubleArrayBox(uint doubleArrayBoxId) { return doubleArrayBoxes.GetValue(doubleArrayBoxId); }
-    #endregion
-
-    #region DictionaryBox
-    public uint GetDictionaryBoxId(DictionaryBox dictionaryBox) { return dictionaryBoxes.GetIndex(dictionaryBox); }
-    public DictionaryBox GetDictionaryBox(uint dictionaryBoxId) { return dictionaryBoxes.GetValue(dictionaryBoxId); }
-    #endregion
-
-    #region StorableClassBox
-    public uint GetStorableClassBoxId(StorableClassBox storableClassBox) { return storableClassBoxes.GetIndex(storableClassBox); }
-    public StorableClassBox GetStorableClassBox(uint storableClassBoxId) { return storableClassBoxes.GetValue(storableClassBoxId); }
-    #endregion
-    #endregion
     #endregion
 
@@ -243,18 +164,5 @@
       bundle.TypeGuids.AddRange(mapper.types.GetValues().Select(x => ByteString.CopyFrom(StaticCache.GetGuid(x).ToByteArray())));
       bundle.Boxes.AddRange(mapper.boxId2Box.OrderBy(x => x.Key).Select(x => x.Value));
-      bundle.TypeBoxes.AddRange(mapper.typeBoxes.GetValues());
-
       bundle.Strings.AddRange(mapper.strings.GetValues());
-
-      bundle.BoolArrayBoxes.AddRange(mapper.boolArrayBoxes.GetValues());
-      bundle.IntArrayBoxes.AddRange(mapper.intArrayBoxes.GetValues());
-      bundle.UnsignedIntArrayBoxes.AddRange(mapper.unsignedIntArrayBoxes.GetValues());
-      bundle.LongArrayBoxes.AddRange(mapper.longArrayBoxes.GetValues());
-      bundle.UnsignedLongArrayBoxes.AddRange(mapper.unsignedLongArrayBoxes.GetValues());
-      bundle.FloatArrayBoxes.AddRange(mapper.floatArrayBoxes.GetValues());
-      bundle.DoubleArrayBoxes.AddRange(mapper.doubleArrayBoxes.GetValues());
-
-      bundle.DictionaryBoxes.AddRange(mapper.dictionaryBoxes.GetValues());
-      bundle.StorableClassBoxes.AddRange(mapper.storableClassBoxes.GetValues());
 
       return bundle;
@@ -265,20 +173,6 @@
       mapper.transformers = new Index<ITransformer>(bundle.TransformerGuids.Select(x => new Guid(x.ToByteArray())).Select(StaticCache.GetTransformer));
       mapper.types = new Index<Type>(bundle.TypeGuids.Select(x => StaticCache.GetType(new Guid(x.ToByteArray()))));
-
       mapper.boxId2Box = bundle.Boxes.Select((b, i) => new { Box = b, Index = i }).ToDictionary(k => (uint)k.Index + 1, v => v.Box);
-      mapper.typeBoxes = new Index<TypeBox>(bundle.TypeBoxes);
-
       mapper.strings = new Index<string>(bundle.Strings);
-
-      mapper.boolArrayBoxes = new Index<BoolArrayBox>(bundle.BoolArrayBoxes);
-      mapper.intArrayBoxes = new Index<IntArrayBox>(bundle.IntArrayBoxes);
-      mapper.unsignedIntArrayBoxes = new Index<UnsignedIntArrayBox>(bundle.UnsignedIntArrayBoxes);
-      mapper.longArrayBoxes = new Index<LongArrayBox>(bundle.LongArrayBoxes);
-      mapper.unsignedLongArrayBoxes = new Index<UnsignedLongArrayBox>(bundle.UnsignedLongArrayBoxes);
-      mapper.floatArrayBoxes = new Index<FloatArrayBox>(bundle.FloatArrayBoxes);
-      mapper.doubleArrayBoxes = new Index<DoubleArrayBox>(bundle.DoubleArrayBoxes);
-
-      mapper.dictionaryBoxes = new Index<DictionaryBox>(bundle.DictionaryBoxes);
-      mapper.storableClassBoxes = new Index<StorableClassBox>(bundle.StorableClassBoxes);
 
       return mapper.GetObject(bundle.RootBoxId);
Index: /branches/PersistenceReintegration/HeuristicLab.Persistence/4.0/Core/StaticCache.cs
===================================================================
--- /branches/PersistenceReintegration/HeuristicLab.Persistence/4.0/Core/StaticCache.cs	(revision 15528)
+++ /branches/PersistenceReintegration/HeuristicLab.Persistence/4.0/Core/StaticCache.cs	(revision 15529)
@@ -25,4 +25,5 @@
 using System.Drawing;
 using System.Linq;
+using System.Reflection;
 using HeuristicLab.PluginInfrastructure;
 
@@ -36,4 +37,5 @@
     private readonly Dictionary<Type, Guid> type2Guid;
     private readonly Dictionary<Type, TypeInfo> typeInfos;
+    private readonly Dictionary<Guid, List<MethodInfo>> guid2ConversionMethods;
 
     internal StaticCache() {
@@ -43,4 +45,5 @@
       type2Guid = new Dictionary<Type, Guid>();
       typeInfos = new Dictionary<Type, TypeInfo>();
+      guid2ConversionMethods = new Dictionary<Guid, List<MethodInfo>>();
 
       foreach (var transformer in ApplicationManager.Manager.GetInstances<ITransformer>())
@@ -108,4 +111,9 @@
             if (StorableTypeAttribute.IsStorableType(t)) {
               RegisterType(StorableTypeAttribute.GetStorableTypeAttribute(t).Guid, t);
+            }
+            foreach (var mi in t.GetMethods(BindingFlags.NonPublic | BindingFlags.Static)) {
+              if (StorableConversionAttribute.IsStorableConversionMethod(mi)) {
+                RegisterStorableConversion(StorableConversionAttribute.GetStorableConversionAttribute(mi).Guid, mi);
+              }
             }
           }
@@ -149,4 +157,12 @@
       }
     }
+    public void RegisterStorableConversion(Guid guid, MethodInfo methodInfo) {
+      lock (locker) {
+        List<MethodInfo> conversionMethods;
+        if (!guid2ConversionMethods.TryGetValue(guid, out conversionMethods))
+          guid2ConversionMethods.Add(guid, conversionMethods = new List<MethodInfo>());
+        conversionMethods.Add(methodInfo);
+      }
+    }
 
     // mainly for testing
@@ -186,4 +202,10 @@
       }
     }
+
+    public IEnumerable<MethodInfo> GetStorableConversions(Guid guid) {
+      List<MethodInfo> conversionMethods;
+      if (guid2ConversionMethods.TryGetValue(guid, out conversionMethods)) return conversionMethods;
+      return Enumerable.Empty<MethodInfo>();
+    }
   }
 }
Index: /branches/PersistenceReintegration/HeuristicLab.Persistence/4.0/Core/StorableConversionAttribute.cs
===================================================================
--- /branches/PersistenceReintegration/HeuristicLab.Persistence/4.0/Core/StorableConversionAttribute.cs	(revision 15528)
+++ /branches/PersistenceReintegration/HeuristicLab.Persistence/4.0/Core/StorableConversionAttribute.cs	(revision 15529)
@@ -27,9 +27,9 @@
   public sealed class StorableConversionAttribute : Attribute {
     public Guid Guid { get; private set; }
-    public uint SrcVersion { get; private set; }
+    public uint Version { get; private set; }
 
-    public StorableConversionAttribute(string guid, uint srcVersion) {
+    public StorableConversionAttribute(string guid, uint version) {
       this.Guid = new Guid(guid);
-      this.SrcVersion = srcVersion;
+      this.Version = version;
     }
 
@@ -45,5 +45,5 @@
     }
     public static uint GetVersion(MethodInfo mi) {
-      return GetStorableConversionAttribute(mi).SrcVersion;
+      return GetStorableConversionAttribute(mi).Version;
     }
   }
Index: /branches/PersistenceReintegration/HeuristicLab.Persistence/4.0/Core/TypeInfo.cs
===================================================================
--- /branches/PersistenceReintegration/HeuristicLab.Persistence/4.0/Core/TypeInfo.cs	(revision 15528)
+++ /branches/PersistenceReintegration/HeuristicLab.Persistence/4.0/Core/TypeInfo.cs	(revision 15529)
@@ -58,15 +58,9 @@
       StorableTypeAttribute = StorableTypeAttribute.GetStorableTypeAttribute(type);
       if (StorableTypeAttribute != null) {
-        // check constructors (
+        string guidPrefix = StorableTypeAttribute.Guid.ToString().ToUpper();
+        // check constructors
         if (!type.IsValueType && !type.IsEnum && !type.IsInterface &&
           GetStorableConstructor() == null && GetDefaultConstructor() == null)
           throw new PersistenceException("No storable constructor or parameterless constructor found.");
-
-        // traverse type hierarchy from base type to sub types
-        Stack<Type> types = new Stack<Type>();
-        while (type != null) {
-          types.Push(type);
-          type = type.BaseType;
-        }
 
         var fields = new List<ComponentInfo>();
@@ -74,45 +68,49 @@
         var beforeSerializationHooks = new List<MethodInfo>();
         var afterDeserializationHooks = new List<MethodInfo>();
-        while (types.Count > 0) {
-          type = types.Pop();
-          if (StorableTypeAttribute.MemberSelection != StorableMemberSelection.AllProperties) {
-            var fieldInfos = type.GetFields(BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic)
-                                 .Where(x => !x.Name.StartsWith("<") && !x.Name.EndsWith("k__BackingField")); // exclude backing fields
-            if (StorableTypeAttribute.MemberSelection == StorableMemberSelection.MarkedOnly)
-              fieldInfos = fieldInfos.Where(x => StorableAttribute.IsStorable(x)).ToArray();
-            foreach (var field in fieldInfos) {
-              var attrib = StorableAttribute.GetStorableAttribute(field);
-              var name = attrib == null || string.IsNullOrEmpty(attrib.Name) ? field.Name : attrib.Name;
-              fields.Add(new ComponentInfo(type.Name + '.' + name, field, attrib, true, true));
-            }
-          }
 
-          if (StorableTypeAttribute.MemberSelection != StorableMemberSelection.AllFields) {
-            var propertyInfos = type.GetProperties(BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic).
-                        Where(x => x.GetIndexParameters().Length == 0);  // exclude indexed properties
-            if (StorableTypeAttribute.MemberSelection == StorableMemberSelection.MarkedOnly)
-              propertyInfos = propertyInfos.Where(x => StorableAttribute.IsStorable(x)).ToArray();
-            foreach (var property in propertyInfos) {
-              var attrib = StorableAttribute.GetStorableAttribute(property);
-              if ((!property.CanRead || !property.CanWrite) && (attrib == null || !attrib.AllowOneWay))
-                throw new PersistenceException("Properties must be readable and writable or explicity enable one way serialization.");
+        if (StorableTypeAttribute.MemberSelection != StorableMemberSelection.AllProperties) {
+          var fieldInfos = type.GetFields(BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic)
+                               .Where(x => !x.Name.StartsWith("<") && !x.Name.EndsWith("k__BackingField")); // exclude backing fields
 
-              var name = attrib == null || string.IsNullOrEmpty(attrib.Name) ? property.Name : attrib.Name;
-              properties.Add(new ComponentInfo(type.Name + '.' + name, property, attrib, property.CanRead, property.CanWrite));
-            }
-          }
+          if (StorableTypeAttribute.MemberSelection == StorableMemberSelection.MarkedOnly)
+            fieldInfos = fieldInfos.Where(StorableAttribute.IsStorable).ToArray();
 
-          var methodInfos = type.GetMethods(BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic).
-                            Where(x => StorableHookAttribute.IsStorableHook(x)).
-                            Where(x => (x.ReturnType == typeof(void)) && (x.GetParameters().Length == 0));
-          foreach (var method in methodInfos) {
-            foreach (var attrib in StorableHookAttribute.GetStorableHookAttributes(method)) {
-              if (attrib.HookType == HookType.BeforeSerialization)
-                beforeSerializationHooks.Add(method);
-              if (attrib.HookType == HookType.AfterDeserialization)
-                afterDeserializationHooks.Add(method);
-            }
+          foreach (var field in fieldInfos) {
+            var attrib = StorableAttribute.GetStorableAttribute(field);
+            var name = attrib == null || string.IsNullOrEmpty(attrib.Name) ? field.Name : attrib.Name;
+            fields.Add(new ComponentInfo(name, guidPrefix + "." + name, field, attrib, true, true));
           }
         }
+
+        if (StorableTypeAttribute.MemberSelection != StorableMemberSelection.AllFields) {
+          var propertyInfos = type.GetProperties(BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic)
+                                  .Where(x => !x.GetIndexParameters().Any());  // exclude indexed properties
+
+          if (StorableTypeAttribute.MemberSelection == StorableMemberSelection.MarkedOnly)
+            propertyInfos = propertyInfos.Where(StorableAttribute.IsStorable).ToArray();
+
+          foreach (var property in propertyInfos) {
+            var attrib = StorableAttribute.GetStorableAttribute(property);
+            if ((!property.CanRead || !property.CanWrite) && (attrib == null || !attrib.AllowOneWay))
+              throw new PersistenceException("Properties must be readable and writable or have one way serialization explicitly enabled.");
+
+            var name = attrib == null || string.IsNullOrEmpty(attrib.Name) ? property.Name : attrib.Name;
+            properties.Add(new ComponentInfo(name, guidPrefix + "." + name, property, attrib, property.CanRead, property.CanWrite));
+          }
+        }
+
+        var methodInfos = type.GetMethods(BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic)
+                              .Where(StorableHookAttribute.IsStorableHook)
+                              .Where(x => x.ReturnType == typeof(void) && !x.GetParameters().Any());
+
+        foreach (var method in methodInfos) {
+          foreach (var attrib in StorableHookAttribute.GetStorableHookAttributes(method)) {
+            if (attrib.HookType == HookType.BeforeSerialization)
+              beforeSerializationHooks.Add(method);
+            if (attrib.HookType == HookType.AfterDeserialization)
+              afterDeserializationHooks.Add(method);
+          }
+        }
+
         Fields = fields;
         Properties = properties;
@@ -155,13 +153,14 @@
 
     private ConstructorInfo GetStorableConstructor() {
-      return Type.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
-               .Where(x => StorableConstructorAttribute.IsStorableConstructor(x))
-               .Where(x => (x.GetParameters().Length == 1) && (x.GetParameters()[0].ParameterType == typeof(StorableConstructorFlag)))
-               .FirstOrDefault();
+      return (from ctor in Type.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
+              let parameters = ctor.GetParameters()
+              where StorableConstructorAttribute.IsStorableConstructor(ctor)
+                 && parameters.Length == 1
+                 && parameters[0].ParameterType == typeof(StorableConstructorFlag)
+              select ctor).FirstOrDefault();
     }
 
     private ConstructorInfo GetDefaultConstructor() {
-      return Type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
-                             null, Type.EmptyTypes, null);
+      return Type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
     }
   }
Index: /branches/PersistenceReintegration/HeuristicLab.Persistence/4.0/Protos/PersistenceMessages.proto
===================================================================
--- /branches/PersistenceReintegration/HeuristicLab.Persistence/4.0/Protos/PersistenceMessages.proto	(revision 15528)
+++ /branches/PersistenceReintegration/HeuristicLab.Persistence/4.0/Protos/PersistenceMessages.proto	(revision 15529)
@@ -9,68 +9,33 @@
   uint32 root_box_id = 10;
   repeated Box boxes = 20;
-  repeated TypeBox type_boxes = 30;
+  repeated string strings = 30;
+}
 
-  repeated string strings = 100;
-
-  repeated BoolArrayBox bool_array_boxes = 200;
-  repeated IntArrayBox int_array_boxes = 201;
-  repeated UnsignedIntArrayBox unsigned_int_array_boxes = 203;
-  repeated LongArrayBox long_array_boxes = 202;
-  repeated UnsignedLongArrayBox unsigned_long_array_boxes = 204;
-  repeated FloatArrayBox float_array_boxes = 205;
-  repeated DoubleArrayBox double_array_boxes = 206;
-  
-  repeated DictionaryBox dictionary_boxes = 300;
-  repeated StorableClassBox storable_class_boxes = 310;
-}
 message Box {
   uint32 transformer_id = 1;
-  uint32 type_id = 2;
-  uint32 box_id = 3;
+  uint32 type_box_id = 2;
 
-  bool bool = 10;
-  int32 int = 11;
-  int64 long = 12;
-  uint32 u_int = 13;
-  uint64 u_long = 14;
-  float float = 15;
-  double double = 16;
-  bytes bytes = 17;
+  uint32 type_id = 10;
+  uint32 type_version = 11;
+  repeated uint32 generic_type_box_ids = 12;
+
+  bool bool = 20;
+  int32 int = 21;
+  int64 long = 22;
+  uint32 u_int = 23;
+  uint64 u_long = 24;
+  float float = 25;
+  double double = 26;
+  bytes bytes = 27;
+
+  repeated bool bools = 30;
+  repeated int32 ints = 31;
+  repeated int64 longs = 32;
+  repeated uint32 u_ints = 33;
+  repeated uint64 u_longs = 34;
+  repeated float floats = 35;
+  repeated double doubles = 36;
+
+  map<uint32, uint32> key_value_pairs = 40;
+  uint32 comparer_id = 50;
 }
-message TypeBox {
-  uint32 version = 1;
-  repeated uint32 generic_type_ids = 2;
-}
-
-// array boxes
-message StringArrayBox { repeated string values = 1; }
-message BoolArrayBox { repeated bool values = 1; }
-message IntArrayBox { repeated int32 values = 1; }
-message LongArrayBox { repeated int64 values = 1; }
-message UnsignedIntArrayBox { repeated uint32 values = 1; }
-message UnsignedLongArrayBox { repeated uint64 values = 1; }
-message FloatArrayBox { repeated float values = 1; }
-message DoubleArrayBox { repeated double values = 1; }
-
-// matrix boxes
-message MatrixBox {
-  uint32 element_type_id = 1;
-  repeated uint32 lengths = 2;
-}
-message BoolMatrixBox {
-  MatrixBox matrixBox = 1;
-  repeated bool values = 2;
-}
-message IntMatrixBox {
-  MatrixBox matrixBox = 1;
-  repeated int32 values = 2;
-}
-
-// composite boxes
-message DictionaryBox {
-  map<uint32, uint32> key_value_pairs = 1;
-  uint32 comparer_id = 2;
-}
-message StorableClassBox {
-  map<uint32, uint32> key_value_pairs = 1;
-}
Index: /branches/PersistenceReintegration/HeuristicLab.Persistence/4.0/Transformers/Transformers.cs
===================================================================
--- /branches/PersistenceReintegration/HeuristicLab.Persistence/4.0/Transformers/Transformers.cs	(revision 15528)
+++ /branches/PersistenceReintegration/HeuristicLab.Persistence/4.0/Transformers/Transformers.cs	(revision 15529)
@@ -41,5 +41,5 @@
       var box = new Box {
         TransformerId = mapper.GetTransformerId(this),
-        TypeId = mapper.GetBoxId(o.GetType())
+        TypeBoxId = mapper.GetBoxId(o.GetType())
       };
       Populate(box, (T)o, mapper);
@@ -48,5 +48,5 @@
 
     public override object ToObject(Box box, Mapper mapper) {
-      return Extract(box, (Type)mapper.GetObject(box.TypeId), mapper);
+      return Extract(box, (Type)mapper.GetObject(box.TypeBoxId), mapper);
     }
 
@@ -63,7 +63,5 @@
 
     public override Box ToBox(object o, Mapper mapper) {
-      var box = new Box {
-        TransformerId = mapper.GetTransformerId(this)
-      };
+      var box = new Box { TransformerId = mapper.GetTransformerId(this) };
       Populate(box, o, mapper);
       return box;
@@ -72,12 +70,11 @@
     private void Populate(Box box, object value, Mapper mapper) {
       var type = (Type)value;
-      var typeBox = new TypeBox();
 
       if (type.IsGenericType) {
         box.TypeId = mapper.GetTypeId(type.GetGenericTypeDefinition());
-        typeBox.GenericTypeIds.AddRange(type.GetGenericArguments().Select(mapper.GetBoxId));
+        box.GenericTypeBoxIds.AddRange(type.GetGenericArguments().Select(mapper.GetBoxId));
       } else if (type.IsArray) {
         box.TypeId = mapper.GetTypeId(typeof(Array));
-        typeBox.GenericTypeIds.Add(mapper.GetBoxId(type.GetElementType()));
+        box.GenericTypeBoxIds.Add(mapper.GetBoxId(type.GetElementType()));
       } else {
         box.TypeId = mapper.GetTypeId(type);
@@ -85,7 +82,5 @@
 
       if (StorableTypeAttribute.IsStorableType(type))
-        typeBox.Version = StorableTypeAttribute.GetStorableTypeAttribute(type).Version;
-
-      box.BoxId = mapper.GetTypeBoxId(typeBox);
+        box.TypeVersion = StorableTypeAttribute.GetStorableTypeAttribute(type).Version;
     }
 
@@ -95,12 +90,9 @@
 
     private object Extract(Box box, Type type, Mapper mapper) {
-      var typeBox = mapper.GetTypeBox(box.BoxId);
-
       if (type.IsGenericType) {
-        return type.MakeGenericType(typeBox.GenericTypeIds.Select(id => (Type)mapper.GetObject(id)).ToArray());
+        return type.MakeGenericType(box.GenericTypeBoxIds.Select(x => (Type)mapper.GetObject(x)).ToArray());
       } else if (type == typeof(Array)) {
-        return ((Type)mapper.GetObject(typeBox.GenericTypeIds[0])).MakeArrayType();
+        return ((Type)mapper.GetObject(box.GenericTypeBoxIds[0])).MakeArrayType();
       } else {
-
         return type;
       }
@@ -202,14 +194,6 @@
   [StorableType("4397B775-7D48-4C2A-8D28-ACC8C196CF70")]
   internal sealed class StringArrayBoxTransformer : BoxTransformer<string[]> {
-    protected override void Populate(Box box, string[] value, Mapper mapper) {
-      var unsignedIntArrayBox = new UnsignedIntArrayBox();
-      unsignedIntArrayBox.Values.AddRange(value.Select(mapper.GetStringId));
-      box.BoxId = mapper.GetUnsignedIntArrayBoxId(unsignedIntArrayBox);
-    }
-
-    protected override string[] Extract(Box box, Type type, Mapper mapper) {
-      var unsignedIntArrayBox = mapper.GetUnsignedIntArrayBox(box.BoxId);
-      return unsignedIntArrayBox.Values.Select(mapper.GetString).ToArray();
-    }
+    protected override void Populate(Box box, string[] value, Mapper mapper) { box.UInts.AddRange(value.Select(mapper.GetStringId)); }
+    protected override string[] Extract(Box box, Type type, Mapper mapper) { return box.UInts.Select(mapper.GetString).ToArray(); }
   }
 
@@ -217,14 +201,6 @@
   [StorableType("9719DB59-C6BC-4788-BBB0-389A1B49CFEE")]
   internal sealed class BoolArrayBoxTransformer : BoxTransformer<bool[]> {
-    protected override void Populate(Box box, bool[] value, Mapper mapper) {
-      var boolArrayBox = new BoolArrayBox();
-      boolArrayBox.Values.AddRange(value);
-      box.BoxId = mapper.GetBoolArrayBoxId(boolArrayBox);
-    }
-
-    protected override bool[] Extract(Box box, Type type, Mapper mapper) {
-      var boolArrayBox = mapper.GetBoolArrayBox(box.BoxId);
-      return boolArrayBox.Values.ToArray();
-    }
+    protected override void Populate(Box box, bool[] value, Mapper mapper) { box.Bools.AddRange(value); }
+    protected override bool[] Extract(Box box, Type type, Mapper mapper) { return box.Bools.ToArray(); }
   }
 
@@ -232,14 +208,6 @@
   [StorableType("6548E9F0-621D-47BA-A605-8A47EF85C231")]
   internal sealed class IntArrayBoxTransformer : BoxTransformer<int[]> {
-    protected override void Populate(Box box, int[] value, Mapper mapper) {
-      var intArrayBox = new IntArrayBox();
-      intArrayBox.Values.AddRange(value);
-      box.BoxId = mapper.GetIntArrayBoxId(intArrayBox);
-    }
-
-    protected override int[] Extract(Box box, Type type, Mapper mapper) {
-      var intArrayBox = mapper.GetIntArrayBox(box.BoxId);
-      return intArrayBox.Values.ToArray();
-    }
+    protected override void Populate(Box box, int[] value, Mapper mapper) { box.Ints.AddRange(value); }
+    protected override int[] Extract(Box box, Type type, Mapper mapper) { return box.Ints.ToArray(); }
   }
 
@@ -247,14 +215,6 @@
   [StorableType("4127B466-AFC0-4050-8C45-1376A0E3E016")]
   internal sealed class UnsignedIntArrayBoxTransformer : BoxTransformer<uint[]> {
-    protected override void Populate(Box box, uint[] value, Mapper mapper) {
-      var unsignedIntArrayBox = new UnsignedIntArrayBox();
-      unsignedIntArrayBox.Values.AddRange(value);
-      box.BoxId = mapper.GetUnsignedIntArrayBoxId(unsignedIntArrayBox);
-    }
-
-    protected override uint[] Extract(Box box, Type type, Mapper mapper) {
-      var unsignedIntArrayBox = mapper.GetUnsignedIntArrayBox(box.BoxId);
-      return unsignedIntArrayBox.Values.ToArray();
-    }
+    protected override void Populate(Box box, uint[] value, Mapper mapper) { box.UInts.AddRange(value); }
+    protected override uint[] Extract(Box box, Type type, Mapper mapper) { return box.UInts.ToArray(); }
   }
 
@@ -262,14 +222,6 @@
   [StorableType("C2ED50C8-C340-40C1-B00C-2F398EB709A0")]
   internal sealed class LongArrayBoxTransformer : BoxTransformer<long[]> {
-    protected override void Populate(Box box, long[] value, Mapper mapper) {
-      var longArrayBox = new LongArrayBox();
-      longArrayBox.Values.AddRange(value);
-      box.BoxId = mapper.GetLongArrayBoxId(longArrayBox);
-    }
-
-    protected override long[] Extract(Box box, Type type, Mapper mapper) {
-      var longArrayBox = mapper.GetLongArrayBox(box.BoxId);
-      return longArrayBox.Values.ToArray();
-    }
+    protected override void Populate(Box box, long[] value, Mapper mapper) { box.Longs.AddRange(value); }
+    protected override long[] Extract(Box box, Type type, Mapper mapper) { return box.Longs.ToArray(); }
   }
 
@@ -277,14 +229,6 @@
   [StorableType("641AE353-5373-4811-BACB-C13D3144809C")]
   internal sealed class UnsignedLongArrayBoxTransformer : BoxTransformer<ulong[]> {
-    protected override void Populate(Box box, ulong[] value, Mapper mapper) {
-      var unsignedLongArrayBox = new UnsignedLongArrayBox();
-      unsignedLongArrayBox.Values.AddRange(value);
-      box.BoxId = mapper.GetUnsignedLongArrayBoxId(unsignedLongArrayBox);
-    }
-
-    protected override ulong[] Extract(Box box, Type type, Mapper mapper) {
-      var unsignedLongArrayBox = mapper.GetUnsignedLongArrayBox(box.BoxId);
-      return unsignedLongArrayBox.Values.ToArray();
-    }
+    protected override void Populate(Box box, ulong[] value, Mapper mapper) { box.ULongs.AddRange(value); }
+    protected override ulong[] Extract(Box box, Type type, Mapper mapper) { return box.ULongs.ToArray(); }
   }
 
@@ -292,14 +236,6 @@
   [StorableType("AEE9384F-3857-4CE4-AE30-B99474F7A6C9")]
   internal sealed class FloatArrayBoxTransformer : BoxTransformer<float[]> {
-    protected override void Populate(Box box, float[] value, Mapper mapper) {
-      var floatArrayBox = new FloatArrayBox();
-      floatArrayBox.Values.AddRange(value);
-      box.BoxId = mapper.GetFloatArrayBoxId(floatArrayBox);
-    }
-
-    protected override float[] Extract(Box box, Type type, Mapper mapper) {
-      var floatArrayBox = mapper.GetFloatArrayBox(box.BoxId);
-      return floatArrayBox.Values.ToArray();
-    }
+    protected override void Populate(Box box, float[] value, Mapper mapper) { box.Floats.AddRange(value); }
+    protected override float[] Extract(Box box, Type type, Mapper mapper) { return box.Floats.ToArray(); }
   }
 
@@ -307,14 +243,6 @@
   [StorableType("17D0BA74-CB84-405C-8DBB-D9E361274A0A")]
   internal sealed class DoubleArrayBoxTransformer : BoxTransformer<double[]> {
-    protected override void Populate(Box box, double[] value, Mapper mapper) {
-      var doubleArrayBox = new DoubleArrayBox();
-      doubleArrayBox.Values.AddRange(value);
-      box.BoxId = mapper.GetDoubleArrayBoxId(doubleArrayBox);
-    }
-
-    protected override double[] Extract(Box box, Type type, Mapper mapper) {
-      var doubleArrayBox = mapper.GetDoubleArrayBox(box.BoxId);
-      return doubleArrayBox.Values.ToArray();
-    }
+    protected override void Populate(Box box, double[] value, Mapper mapper) { box.Doubles.AddRange(value); }
+    protected override double[] Extract(Box box, Type type, Mapper mapper) { return box.Doubles.ToArray(); }
   }
 
@@ -322,11 +250,6 @@
   [StorableType("A076D11E-89AA-43C8-87F5-A0D0F52569EB")]
   internal sealed class ByteArrayBoxTransformer : BoxTransformer<byte[]> {
-    protected override void Populate(Box box, byte[] value, Mapper mapper) {
-      box.Bytes = ByteString.CopyFrom(value);
-    }
-
-    protected override byte[] Extract(Box box, Type type, Mapper mapper) {
-      return box.Bytes.ToArray();
-    }
+    protected override void Populate(Box box, byte[] value, Mapper mapper) { box.Bytes = ByteString.CopyFrom(value); }
+    protected override byte[] Extract(Box box, Type type, Mapper mapper) { return box.Bytes.ToArray(); }
   }
 
@@ -334,11 +257,6 @@
   [StorableType("74F6FD4B-D7D7-43CD-B28B-3A775505FEE3")]
   internal sealed class SByteArrayBoxTransformer : BoxTransformer<sbyte[]> {
-    protected override void Populate(Box box, sbyte[] value, Mapper mapper) {
-      box.Bytes = ByteString.CopyFrom(value.Select(x => (byte)x).ToArray());
-    }
-
-    protected override sbyte[] Extract(Box box, Type type, Mapper mapper) {
-      return box.Bytes.Select(x => (sbyte)x).ToArray();
-    }
+    protected override void Populate(Box box, sbyte[] value, Mapper mapper) { box.Bytes = ByteString.CopyFrom(value.Select(x => (byte)x).ToArray()); }
+    protected override sbyte[] Extract(Box box, Type type, Mapper mapper) { return box.Bytes.Select(x => (sbyte)x).ToArray(); }
   }
 
@@ -420,20 +338,17 @@
       var rank = array.Rank;
 
-      var uIntArrayBox = new UnsignedIntArrayBox();
-      uIntArrayBox.Values.Add(mapper.GetBoxId(rank));
+      var uints = box.UInts;
+      uints.Add((uint)rank);
 
       int[] lengths = new int[rank];
       int[] lowerBounds = new int[rank];
       for (int i = 0; i < rank; i++) {
-        lengths[i] = array.GetLength(i);
-        lowerBounds[i] = array.GetLowerBound(i);
-      }
-
-      uIntArrayBox.Values.AddRange(lengths.Select(x => mapper.GetBoxId(x)));
-      uIntArrayBox.Values.AddRange(lowerBounds.Select(x => mapper.GetBoxId(x)));
+        uints.Add(mapper.GetBoxId(lengths[i] = array.GetLength(i)));
+        uints.Add(mapper.GetBoxId(lowerBounds[i] = array.GetLowerBound(i)));
+      }
 
       int[] positions = (int[])lowerBounds.Clone();
       while (positions[rank - 1] < lengths[rank - 1] + lowerBounds[rank - 1]) {
-        uIntArrayBox.Values.Add(mapper.GetBoxId(array.GetValue(positions)));
+        uints.Add(mapper.GetBoxId(array.GetValue(positions)));
         positions[0] += 1;
         for (int i = 0; i < rank - 1; i++) {
@@ -446,17 +361,15 @@
         }
       }
-
-      box.BoxId = mapper.GetUnsignedIntArrayBoxId(uIntArrayBox);
     }
 
     protected override object Extract(Box box, Type type, Mapper mapper) {
-      var uIntArrayBox = mapper.GetUnsignedIntArrayBox(box.BoxId);
-      var rank = (int)mapper.GetObject(uIntArrayBox.Values[0]);
+      var uints = box.UInts;
+      var rank = (int)uints[0];
 
       int[] lengths = new int[rank], lowerBounds = new int[rank];
-      for (int i = 0; i < rank; i++)
-        lengths[i] = (int)mapper.GetObject(uIntArrayBox.Values[i + 1]);
-      for (int i = 0; i < rank; i++)
-        lowerBounds[i] = (int)mapper.GetObject(uIntArrayBox.Values[i + 1 + rank]);
+      for (int i = 0; i < rank; i++) {
+        lengths[i] = (int)mapper.GetObject(uints[2 * i + 1]);
+        lowerBounds[i] = (int)mapper.GetObject(uints[2 * i + 2]);
+      }
 
       return Array.CreateInstance(type.GetElementType(), lengths, lowerBounds);
@@ -465,15 +378,15 @@
     public override void FillFromBox(object obj, Box box, Mapper mapper) {
       var array = (Array)obj;
-      var uIntArrayBox = mapper.GetUnsignedIntArrayBox(box.BoxId);
-      var rank = (int)mapper.GetObject(uIntArrayBox.Values[0]);
+      var uints = box.UInts;
+      var rank = (int)uints[0];
 
       int[] lengths = new int[rank], lowerBounds = new int[rank];
-      for (int i = 0; i < rank; i++)
-        lengths[i] = (int)mapper.GetObject(uIntArrayBox.Values[i + 1]);
-      for (int i = 0; i < rank; i++)
-        lowerBounds[i] = (int)mapper.GetObject(uIntArrayBox.Values[i + 1 + rank]);
+      for (int i = 0; i < rank; i++) {
+        lengths[i] = (int)mapper.GetObject(uints[2 * i + 1]);
+        lowerBounds[i] = (int)mapper.GetObject(uints[2 * i + 2]);
+      }
 
       int[] positions = (int[])lowerBounds.Clone();
-      var e = uIntArrayBox.Values.Skip(1 + 2 * rank).GetEnumerator();
+      var e = uints.Skip(1 + 2 * rank).GetEnumerator();
       while (e.MoveNext()) {
         int[] currentPositions = positions;
@@ -507,24 +420,21 @@
 
     protected override void Populate(Box box, object value, Mapper mapper) {
-      var uIntArrayBox = new UnsignedIntArrayBox();
+      var uints = box.UInts;
 
       var type = value.GetType();
       var propertyInfo = type.GetProperty("Comparer");
       if (propertyInfo != null) {
-        // TODO: where to store id for comparer box? (atm: first element in int array ...)
         var comparer = propertyInfo.GetValue(value);
         var comparerType = comparer.GetType();
         if (StorableTypeAttribute.IsStorableType(comparerType))
-          uIntArrayBox.Values.Add(mapper.GetBoxId(comparer));
+          box.ComparerId = mapper.GetBoxId(comparer);
         else if (comparerType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy).Any())
           throw new NotSupportedException("Cannot serialize non-storable equality comparers with fields");
         else
-          uIntArrayBox.Values.Add(mapper.GetBoxId(comparerType));
+          box.ComparerId = mapper.GetBoxId(comparerType);
       }
 
       foreach (var item in (IEnumerable)value)
-        uIntArrayBox.Values.Add(mapper.GetBoxId(item));
-
-      box.BoxId = mapper.GetUnsignedIntArrayBoxId(uIntArrayBox);
+        uints.Add(mapper.GetBoxId(item));
     }
 
@@ -534,6 +444,6 @@
 
     public override void FillFromBox(object obj, Box box, Mapper mapper) {
-      var uIntArrayBox = mapper.GetUnsignedIntArrayBox(box.BoxId);
-      var elements = uIntArrayBox.Values.Select(mapper.GetObject);
+      var uints = box.UInts;
+      var elements = uints.Select(mapper.GetObject);
       var type = obj.GetType();
 
@@ -548,8 +458,7 @@
         if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(HashSet<>)) {
           var fieldInfo = type.GetField("m_comparer", BindingFlags.NonPublic | BindingFlags.Instance);
-          var comparerObj = mapper.GetObject(uIntArrayBox.Values[0]);
+          var comparerObj = mapper.GetObject(box.ComparerId);
           var comparer = comparerObj is Type ? Activator.CreateInstance((Type)comparerObj) : comparerObj;
           fieldInfo.SetValue(obj, comparer);
-          elements = elements.Skip(1);
         }
       }
@@ -569,8 +478,7 @@
 
     protected override void Populate(Box box, object value, Mapper mapper) {
-      var dictionaryBox = new DictionaryBox();
-      foreach (DictionaryEntry item in (IDictionary)value) {
-        dictionaryBox.KeyValuePairs.Add(mapper.GetBoxId(item.Key), mapper.GetBoxId(item.Value));
-      }
+      var kvps = box.KeyValuePairs;
+      foreach (DictionaryEntry item in (IDictionary)value)
+        kvps.Add(mapper.GetBoxId(item.Key), mapper.GetBoxId(item.Value));
 
       var type = value.GetType();
@@ -580,22 +488,18 @@
       var comparerType = comparer.GetType();
       if (StorableTypeAttribute.IsStorableType(comparerType))
-        dictionaryBox.ComparerId = mapper.GetBoxId(comparer);
+        box.ComparerId = mapper.GetBoxId(comparer);
       else if (comparerType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy).Any())
         throw new NotSupportedException("Cannot serialize non-storable equality comparers with fields");
       else
-        dictionaryBox.ComparerId = mapper.GetBoxId(comparerType);
-
-      box.BoxId = mapper.GetDictionaryBoxId(dictionaryBox);
+        box.ComparerId = mapper.GetBoxId(comparerType);
     }
 
     protected override object Extract(Box box, Type type, Mapper mapper) {
-      var dictionaryBox = mapper.GetDictionaryBox(box.BoxId);
-      return Activator.CreateInstance(type, dictionaryBox.KeyValuePairs.Count);
+      return Activator.CreateInstance(type, box.KeyValuePairs.Count);
     }
 
     public override void FillFromBox(object obj, Box box, Mapper mapper) {
       var type = obj.GetType();
-      var dictionaryBox = mapper.GetDictionaryBox(box.BoxId);
-      var comparerObj = mapper.GetObject(dictionaryBox.ComparerId);
+      var comparerObj = mapper.GetObject(box.ComparerId);
       var comparer = comparerObj is Type ? Activator.CreateInstance((Type)comparerObj) : comparerObj;
 
@@ -604,5 +508,6 @@
 
       var addMethod = type.GetMethod("Add");
-      foreach (var entry in dictionaryBox.KeyValuePairs) {
+      var kvps = box.KeyValuePairs;
+      foreach (var entry in kvps) {
         var key = mapper.GetObject(entry.Key);
         var value = mapper.GetObject(entry.Value);
@@ -670,11 +575,6 @@
   [StorableType("9D99D155-E3BB-40CE-AF64-6E153D876148")]
   internal sealed class DateTimeBoxTransformer : BoxTransformer<DateTime> {
-    protected override void Populate(Box box, DateTime value, Mapper mapper) {
-      box.Long = value.Ticks;
-    }
-
-    protected override DateTime Extract(Box box, Type type, Mapper mapper) {
-      return new DateTime(box.Long);
-    }
+    protected override void Populate(Box box, DateTime value, Mapper mapper) { box.Long = value.Ticks; }
+    protected override DateTime Extract(Box box, Type type, Mapper mapper) { return new DateTime(box.Long); }
   }
 
@@ -682,11 +582,6 @@
   [StorableType("9CA7C1F7-784C-48D5-A6F4-E1FD7B3A2FEC")]
   internal sealed class TimeSpanBoxTransformer : BoxTransformer<TimeSpan> {
-    protected override void Populate(Box box, TimeSpan value, Mapper mapper) {
-      box.Long = value.Ticks;
-    }
-
-    protected override TimeSpan Extract(Box box, Type type, Mapper mapper) {
-      return new TimeSpan(box.Long);
-    }
+    protected override void Populate(Box box, TimeSpan value, Mapper mapper) { box.Long = value.Ticks; }
+    protected override TimeSpan Extract(Box box, Type type, Mapper mapper) { return new TimeSpan(box.Long); }
   }
 
@@ -695,12 +590,10 @@
   internal sealed class PointTransformer : BoxTransformer<Point> {
     protected override void Populate(Box box, Point value, Mapper mapper) {
-      var intArrayBox = new IntArrayBox();
-      intArrayBox.Values.AddRange(new[] { value.X, value.Y });
-      box.BoxId = mapper.GetIntArrayBoxId(intArrayBox);
+      box.Ints.AddRange(new[] { value.X, value.Y });
     }
 
     protected override Point Extract(Box box, Type type, Mapper mapper) {
-      var intArrayBox = mapper.GetIntArrayBox(box.BoxId);
-      return new Point(intArrayBox.Values[0], intArrayBox.Values[1]);
+      var ints = box.Ints;
+      return new Point(ints[0], ints[1]);
     }
   }
@@ -730,17 +623,15 @@
   internal sealed class FontTransformer : BoxTransformer<Font> {
     protected override void Populate(Box box, Font value, Mapper mapper) {
-      var unsignedIntArrayBox = new UnsignedIntArrayBox();
-      unsignedIntArrayBox.Values.Add(mapper.GetStringId(GetFontFamilyName(value.FontFamily)));
-      unsignedIntArrayBox.Values.Add(mapper.GetBoxId(value.Size));
-      unsignedIntArrayBox.Values.Add(mapper.GetBoxId(value.Style));
-      unsignedIntArrayBox.Values.Add(mapper.GetBoxId(value.Unit));
-      unsignedIntArrayBox.Values.Add(mapper.GetBoxId(value.GdiCharSet));
-      unsignedIntArrayBox.Values.Add(mapper.GetBoxId(value.GdiVerticalFont));
-      box.BoxId = mapper.GetUnsignedIntArrayBoxId(unsignedIntArrayBox);
+      var uints = box.UInts;
+      uints.Add(mapper.GetStringId(GetFontFamilyName(value.FontFamily)));
+      uints.Add(mapper.GetBoxId(value.Size));
+      uints.Add(mapper.GetBoxId(value.Style));
+      uints.Add(mapper.GetBoxId(value.Unit));
+      uints.Add(mapper.GetBoxId(value.GdiCharSet));
+      uints.Add(mapper.GetBoxId(value.GdiVerticalFont));
     }
 
     protected override Font Extract(Box box, Type type, Mapper mapper) {
-      var value = mapper.GetUnsignedIntArrayBox(box.BoxId);
-      var fontData = value.Values;
+      var fontData = box.UInts;
       return new Font(
         GetFontFamily(mapper.GetString(fontData[0])),
@@ -780,17 +671,19 @@
 
     protected override void Populate(Box box, object value, Mapper mapper) {
-      var unsignedIntArrayBox = new UnsignedIntArrayBox();
+      var uints = box.UInts;
+
       var type = value.GetType();
-      var pair = new uint[2];
-      pair[0] = mapper.GetBoxId(type.GetProperty("Key").GetValue(value));
-      pair[1] = mapper.GetBoxId(type.GetProperty("Value").GetValue(value));
-      unsignedIntArrayBox.Values.AddRange(pair);
-      box.BoxId = mapper.GetUnsignedIntArrayBoxId(unsignedIntArrayBox);
+      var pair = new[] {
+        mapper.GetBoxId(type.GetProperty("Key").GetValue(value)) ,
+        mapper.GetBoxId(type.GetProperty("Value").GetValue(value))
+      };
+
+      uints.AddRange(pair);
     }
 
     public override void FillFromBox(object obj, Box box, Mapper mapper) {
-      var b = mapper.GetUnsignedIntArrayBox(box.BoxId);
-      var key = mapper.GetObject(b.Values[0]);
-      var val = mapper.GetObject(b.Values[1]);
+      var uints = box.UInts;
+      var key = mapper.GetObject(uints[0]);
+      var val = mapper.GetObject(uints[1]);
       var type = obj.GetType();
       //DataMemberAccessor.GenerateFieldSetter(type.GetField("key", BindingFlags.NonPublic | BindingFlags.Instance))(obj, key);
@@ -819,10 +712,9 @@
     protected override void Populate(Box box, object value, Mapper mapper) {
       var type = value.GetType();
-      var uIntArrayBox = new UnsignedIntArrayBox();
+      var uints = box.UInts;
       for (int i = 1; i <= type.GetGenericArguments().Length; i++) {
         string name = string.Format("Item{0}", i);
-        uIntArrayBox.Values.Add(mapper.GetBoxId(type.GetProperty(name).GetValue(value)));
-      }
-      box.BoxId = mapper.GetUnsignedIntArrayBoxId(uIntArrayBox);
+        uints.Add(mapper.GetBoxId(type.GetProperty(name).GetValue(value)));
+      }
     }
 
@@ -835,6 +727,6 @@
 
     public override void FillFromBox(object obj, Box box, Mapper mapper) {
-      var uIntArrayBox = mapper.GetUnsignedIntArrayBox(box.BoxId);
-      var elements = uIntArrayBox.Values.Select(mapper.GetObject).ToArray();
+      var uints = box.UInts;
+      var elements = uints.Select(mapper.GetObject).ToArray();
       var type = obj.GetType();
       for (int i = 1; i <= elements.Length; i++) {
@@ -853,30 +745,16 @@
 
     protected override void Populate(Box box, object value, Mapper mapper) {
-      var b = new StorableClassBox();
       var type = value.GetType();
 
-      var components = new Dictionary<uint, uint>();
-      foreach (var fieldInfo in type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) {
-        var component = mapper.GetBoxId(fieldInfo.GetValue(value));
-        components.Add(mapper.GetStringId(fieldInfo.Name), component);
-      }
-
-      foreach (var component in components) {
-        b.KeyValuePairs.Add(component.Key, component.Value);
-      }
-
-      box.BoxId = mapper.GetStorableClassBoxId(b);
+      var kvps = box.KeyValuePairs;
+      foreach (var fieldInfo in type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
+        kvps.Add(mapper.GetStringId(fieldInfo.Name), mapper.GetBoxId(fieldInfo.GetValue(value)));
     }
 
     protected override object Extract(Box box, Type type, Mapper mapper) {
-      var data = mapper.GetStorableClassBox(box.BoxId);
       var obj = Activator.CreateInstance(type);
 
-      var components = new Dictionary<uint, uint>();
-      foreach (var kvp in data.KeyValuePairs) {
-        components.Add(kvp.Key, kvp.Value);
-      }
-
-      foreach (var t in components) {
+      var kvps = box.KeyValuePairs;
+      foreach (var t in kvps) {
         string name = mapper.GetString(t.Key);
         MemberInfo[] mis = type.GetMember(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
@@ -894,5 +772,4 @@
       return obj;
     }
-
   }
 
@@ -906,31 +783,42 @@
 
     protected override void Populate(Box box, object value, Mapper mapper) {
-      var b = new StorableClassBox();
-      var type = value.GetType();
-      var typeInfo = Mapper.StaticCache.GetTypeInfo(type);
-
+      var kvps = box.KeyValuePairs;
+      var parentTypeVersions = box.UInts;
       var emptyArgs = new object[0];
-      foreach (var hook in typeInfo.BeforeSerializationHooks) {
-        hook.Invoke(value, emptyArgs);
-      }
-
-      var components = new Dictionary<uint, uint>();
-      foreach (var componentInfo in typeInfo.Fields) {
-        var field = (FieldInfo)componentInfo.MemberInfo;
-        var component = mapper.GetBoxId(field.GetValue(value));
-        components.Add(mapper.GetStringId(componentInfo.Name), component);
-      }
-
-      foreach (var componentInfo in typeInfo.Properties.Where(x => x.Readable)) {
-        var property = (PropertyInfo)componentInfo.MemberInfo;
-        var component = mapper.GetBoxId(property.GetValue(value, null));
-        components.Add(mapper.GetStringId(componentInfo.Name), component);
-      }
-
-      foreach (var component in components) {
-        b.KeyValuePairs.Add(component.Key, component.Value);
-      }
-
-      box.BoxId = mapper.GetStorableClassBoxId(b);
+
+      var originalType = value.GetType();
+
+      // traverse type hierarchy
+      var type = originalType;
+      while (StorableTypeAttribute.IsStorableType(type)) {
+        var typeInfo = Mapper.StaticCache.GetTypeInfo(type);
+        var attribute = typeInfo.StorableTypeAttribute;
+        var guid = typeInfo.StorableTypeAttribute.Guid;
+
+        foreach (var hook in typeInfo.BeforeSerializationHooks)
+          hook.Invoke(value, emptyArgs);
+
+        foreach (var componentInfo in typeInfo.Fields) {
+          var field = (FieldInfo)componentInfo.MemberInfo;
+          kvps.Add(
+            mapper.GetStringId(componentInfo.FullName),
+            mapper.GetBoxId(field.GetValue(value))
+          );
+        }
+
+        foreach (var componentInfo in typeInfo.Properties.Where(x => x.Readable)) {
+          var property = (PropertyInfo)componentInfo.MemberInfo;
+          kvps.Add(
+            mapper.GetStringId(componentInfo.FullName),
+            mapper.GetBoxId(property.GetValue(value, null))
+          );
+        }
+
+        if (type != originalType) {
+          parentTypeVersions.AddRange(new[] { mapper.GetStringId(guid.ToString()), attribute.Version });
+        }
+
+        type = type.BaseType;
+      }
     }
 
@@ -940,85 +828,129 @@
 
     public override void FillFromBox(object obj, Box box, Mapper mapper) {
-      var data = mapper.GetStorableClassBox(box.BoxId);
-      var type = obj.GetType();
+      var kvps = box.KeyValuePairs;
+      var parentTypeVersions = box.UInts;
+      var emptyArgs = new object[0];
+
+      var dict = new Dictionary<string, object>();
+      foreach (var entry in kvps) {
+        string key = mapper.GetString(entry.Key);
+        object value = mapper.GetObject(entry.Value);
+        dict.Add(key, value);
+      }
+
+      var type = (Type)mapper.GetObject(box.TypeBoxId);
+      var typeBox = mapper.GetBox(box.TypeBoxId);
       var typeInfo = Mapper.StaticCache.GetTypeInfo(type);
-      var typeBox = mapper.GetTypeBox(mapper.GetBox(box.TypeId).BoxId);
-      var version = Math.Max(typeBox.Version, 1);
-      var typeGuid = typeInfo.StorableTypeAttribute.Guid;
-
-      var components = new Dictionary<uint, uint>();
-      foreach (var kvp in data.KeyValuePairs) {
-        components.Add(kvp.Key, kvp.Value);
-      }
-
-      var conversionMethods =
-        type.Assembly.GetTypes().SelectMany(t =>
-          t.GetMethods(BindingFlags.NonPublic | BindingFlags.Static)
-          .Where(StorableConversionAttribute.IsStorableConversionMethod)
-          .Where(mi => StorableConversionAttribute.GetGuid(mi) == typeGuid &&
-                       StorableConversionAttribute.GetVersion(mi) >= version))
-          .OrderBy(StorableConversionAttribute.GetVersion)
-          .ToArray();
-
-      // put all objects into dictionary for conversion 
-      var dict = new Dictionary<string, object>();
-      foreach (var component in components) {
-        dict.Add(mapper.GetString(component.Key), mapper.GetObject(component.Value));
-      }
-
-      Dictionary<string, object> lastDict = new Dictionary<string, object>();
-      foreach (var convMeth in conversionMethods) {
-        if (StorableConversionAttribute.GetVersion(convMeth) != version)
-          throw new PersistenceException(string.Format("No conversion method defined for type {0} version {1}", typeGuid, version));
-        lastDict = (Dictionary<string, object>)convMeth.Invoke(null, new object[] { dict });
-        foreach (var kvp in lastDict) {
-          dict[kvp.Key] = kvp.Value;
-        }
-        version++;
-      }
-      if (version != typeInfo.StorableTypeAttribute.Version)
-        throw new PersistenceException(string.Format("Missing one or more conversion methods for type {0} version {1}",
-          typeGuid, typeInfo.StorableTypeAttribute.Version));
-
-      // set default values for all fields and properties
-      foreach (var componentInfo in typeInfo.Fields) {
-        var field = (FieldInfo)componentInfo.MemberInfo;
-        if (componentInfo.StorableAttribute != null && componentInfo.StorableAttribute.DefaultValue != null)
-          field.SetValue(obj, componentInfo.StorableAttribute.DefaultValue);
-      }
-      foreach (var componentInfo in typeInfo.Properties.Where(x => x.Writeable)) {
-        var property = (PropertyInfo)componentInfo.MemberInfo;
-        if (componentInfo.StorableAttribute != null && componentInfo.StorableAttribute.DefaultValue != null)
-          property.SetValue(obj, componentInfo.StorableAttribute.DefaultValue, null);
-      }
-
-      // set all members as generated by conversion method chain
-      foreach (var kvp in dict) {
-        var key = kvp.Key;
-        var val = kvp.Value;
-        var fieldInfo = typeInfo.Fields.FirstOrDefault(fi => fi.Name == key);
-        if (fieldInfo != null) {
-          var field = (FieldInfo)fieldInfo.MemberInfo;
-          field.SetValue(obj, val);
-          lastDict.Remove(fieldInfo.Name); // only for consistency check
-          continue;
-        }
-        var propInfo = typeInfo.Properties.Where(x => x.Writeable).FirstOrDefault(pi => pi.Name == key);
-        if (propInfo != null) {
-          var prop = (PropertyInfo)propInfo.MemberInfo;
-          prop.SetValue(obj, val, null);
-          lastDict.Remove(propInfo.Name);    // only for consistency check
-          continue;
-        }
-      }
-
-      if (lastDict.Any())
-        throw new PersistenceException(string.Format("Invalid conversion method. The following members are undefined in type {0} version {1}: {2}",
-          typeGuid, typeInfo.StorableTypeAttribute.Version,
-          string.Join(", ", lastDict.Keys)));
-
-      var emptyArgs = new object[0];
-      foreach (var hook in typeInfo.AfterDeserializationHooks) {
-        hook.Invoke(obj, emptyArgs);
+
+      var typeVersions = new List<Tuple<Guid, uint>>();
+      typeVersions.Add(Tuple.Create(typeInfo.StorableTypeAttribute.Guid, typeBox.TypeVersion));
+      for (int i = 0; i < parentTypeVersions.Count; i += 2)
+        typeVersions.Add(Tuple.Create(Guid.Parse(mapper.GetString(parentTypeVersions[i])), parentTypeVersions[i + 1]));
+
+      var originalType = type;
+      var originalTypeInfo = typeInfo;
+
+      foreach (var entry in typeVersions) {
+        var guid = entry.Item1;
+        var version = entry.Item2;
+
+        var conversionMethods = (from methodInfo in Mapper.StaticCache.GetStorableConversions(guid)
+                                 let attrib = StorableConversionAttribute.GetStorableConversionAttribute(methodInfo)
+                                 where attrib.Version >= version
+                                 orderby attrib.Version
+                                 select methodInfo).ToList();
+
+        uint targetVersion;
+
+        try {
+          type = Mapper.StaticCache.GetType(guid);
+          typeInfo = Mapper.StaticCache.GetTypeInfo(type);
+          targetVersion = typeInfo.StorableTypeAttribute.Version;
+        } catch (KeyNotFoundException) {
+          targetVersion = 0;
+        }
+
+        Dictionary<string, object> lastDict = new Dictionary<string, object>();
+        foreach (var conversionMethod in conversionMethods) {
+          if (StorableConversionAttribute.GetVersion(conversionMethod) != version)
+            throw new PersistenceException(string.Format("No conversion method defined for type {0} version {1}", guid, version));
+
+          lastDict = (Dictionary<string, object>)conversionMethod.Invoke(null, new object[] { dict });
+          foreach (var kvp in lastDict) dict[kvp.Key] = kvp.Value;
+
+          version++;
+        }
+
+        if (version < targetVersion)
+          throw new PersistenceException(string.Format("Missing one or more conversion methods for type {0} version {1}", guid, version));
+      }
+
+      var typeStack = new Stack<Tuple<Type, TypeInfo>>();
+      type = originalType;
+      typeInfo = originalTypeInfo;
+
+      while (StorableTypeAttribute.IsStorableType(type)) {
+        typeInfo = Mapper.StaticCache.GetTypeInfo(type);
+        typeStack.Push(Tuple.Create(type, typeInfo));
+        type = type.BaseType;
+      }
+
+      foreach (var frame in typeStack) {
+        type = frame.Item1;
+        typeInfo = frame.Item2;
+
+        // set default values for all fields and properties
+        foreach (var componentInfo in typeInfo.Fields) {
+          var attrib = componentInfo.StorableAttribute;
+          var fieldInfo = (FieldInfo)componentInfo.MemberInfo;
+          if (attrib != null && attrib.DefaultValue != null)
+            fieldInfo.SetValue(obj, attrib.DefaultValue);
+        }
+        foreach (var componentInfo in typeInfo.Properties.Where(x => x.Writeable)) {
+          var attrib = componentInfo.StorableAttribute;
+          var property = (PropertyInfo)componentInfo.MemberInfo;
+          if (attrib != null && attrib.DefaultValue != null)
+            property.SetValue(obj, attrib.DefaultValue, null);
+        }
+
+        // set all members as generated by conversion method chain
+        foreach (var kvp in dict) {
+          string key = kvp.Key;
+          object val = kvp.Value;
+
+          string[] keyParts = key.Split('.');
+          var guid = Guid.Parse(keyParts[0]);
+          string ident = keyParts[1];
+
+          if (guid != typeInfo.StorableTypeAttribute.Guid) continue;
+
+          var fieldInfo = typeInfo.Fields.FirstOrDefault(fi => fi.Name == ident);
+          if (fieldInfo != null) {
+            var field = (FieldInfo)fieldInfo.MemberInfo;
+            field.SetValue(obj, val);
+            //dict.Remove(guid.ToString().ToUpperInvariant() + "." + fieldInfo.Name); // only for consistency check
+            continue;
+          }
+
+          var propInfo = typeInfo.Properties.Where(x => x.Writeable).FirstOrDefault(fi => fi.Name == ident);
+          if (propInfo != null) {
+            var prop = (PropertyInfo)propInfo.MemberInfo;
+            prop.SetValue(obj, val, null);
+            //dict.Remove(guid.ToString().ToUpperInvariant() + "." + propInfo.Name); // only for consistency check
+            continue;
+          }
+        }
+
+        //var undefinedMembers = dict.Where(x => Guid.Parse(x.Key.Split('.')[0]) == typeInfo.StorableTypeAttribute.Guid);
+
+        //if (undefinedMembers.Any())
+        //  throw new PersistenceException(string.Format("Invalid conversion method. The following members are undefined in type {0} version {1}: {2}",
+        //    typeInfo.StorableTypeAttribute.Guid,
+        //    typeInfo.StorableTypeAttribute.Version,
+        //    string.Join(", ", undefinedMembers.Select(x => x.Key))));
+
+        foreach (var hook in typeInfo.AfterDeserializationHooks) {
+          hook.Invoke(obj, emptyArgs);
+        }
       }
     }
Index: /branches/PersistenceReintegration/HeuristicLab.Tests/HeuristicLab.Persistence-3.3/UseCasesPersistenceNew.cs
===================================================================
--- /branches/PersistenceReintegration/HeuristicLab.Tests/HeuristicLab.Persistence-3.3/UseCasesPersistenceNew.cs	(revision 15528)
+++ /branches/PersistenceReintegration/HeuristicLab.Tests/HeuristicLab.Persistence-3.3/UseCasesPersistenceNew.cs	(revision 15529)
@@ -408,5 +408,5 @@
     }
 
-    public string Profile(Func<object> GenerateDataFunc) {
+    public string Profile(Func<object> GenerateDataFunc, string filename = null) {
       int nrOfRepetitions = 30;
       StringBuilder report = new StringBuilder();
@@ -417,35 +417,35 @@
       }
 
-      report.Append("Performance Report for " + GenerateDataFunc.Method.Name + ": " + Environment.NewLine);
+      //report.Append("Performance Report for " + GenerateDataFunc.Method.Name + ": " + Environment.NewLine);
       report.Append(Environment.NewLine);
-      report.AppendFormat("Avg. old vs. new time for serializing a file; {0};{1};{2}",
+      report.AppendFormat("Avg. old vs. new time for serializing a file; {3};{0};{1};{2}",
               dataList.Select(x => x.OldSerializingTime).Average(),
               dataList.Select(x => x.NewSerializingTime).Average(),
               dataList.Select(x => x.OldSerializingTime.TotalMilliseconds).Average() / dataList.Select(x => x.NewSerializingTime.TotalMilliseconds).Average()
-              );
+              , filename);
       report.Append(Environment.NewLine);
-      report.AppendFormat("Avg. old vs. new time for deserializing a file; {0};{1};{2}",
+      report.AppendFormat("Avg. old vs. new time for deserializing a file; {3};{0};{1};{2}",
               dataList.Select(x => x.OldDeserializingTime).Average(),
               dataList.Select(x => x.NewDeserializingTime).Average(),
               dataList.Select(x => x.OldDeserializingTime.TotalMilliseconds).Average() / dataList.Select(x => x.NewDeserializingTime.TotalMilliseconds).Average()
-              );
+              , filename);
       report.Append(Environment.NewLine);
-      report.AppendFormat("Avg. old vs. new file size (in bytes); {0};{1};{2}",
+      report.AppendFormat("Avg. old vs. new file size (in bytes); {3};{0};{1};{2}",
               dataList.Select(x => x.OldFileSize).Average(),
               dataList.Select(x => x.NewFileSize).Average(),
               dataList.Select(x => x.OldFileSize).Average() / dataList.Select(x => x.NewFileSize).Average()
-              );
+              , filename);
       report.Append(Environment.NewLine);
-      report.AppendFormat("Avg. old vs. new memory consumption for serializing a file (in bytes); {0};{1};{2}",
+      report.AppendFormat("Avg. old vs. new memory consumption for serializing a file (in bytes); {3};{0};{1};{2}",
               dataList.Select(x => x.OldSerializingMemoryConsumed).Average(),
               dataList.Select(x => x.NewSerializingMemoryConsumed).Average(),
               dataList.Select(x => x.OldSerializingMemoryConsumed).Average() / dataList.Select(x => x.NewSerializingMemoryConsumed).Average()
-              );
+              , filename);
       report.Append(Environment.NewLine);
-      report.AppendFormat("Avg. old vs. new memory consumption for deserializing a file (in bytes); {0};{1};{2}",
+      report.AppendFormat("Avg. old vs. new memory consumption for deserializing a file (in bytes); {3};{0};{1};{2}",
               dataList.Select(x => x.OldDeserializingMemoryConsumed).Average(),
               dataList.Select(x => x.NewDeserializingMemoryConsumed).Average(),
               dataList.Select(x => x.OldDeserializingMemoryConsumed).Average() / dataList.Select(x => x.NewDeserializingMemoryConsumed).Average()
-              );
+              , filename);
       report.Append(Environment.NewLine);
 
@@ -2160,10 +2160,10 @@
 
 
-    [StorableType("B72C58C8-3321-4706-AA94-578F57337070", 2)]
+    [StorableType("B72C58C8-3321-4706-AA94-578F57337070")]
     private class NewBaseType {
       [Storable]
       public DoubleValue[] items;
     }
-    [StorableType("00000000-0000-0000-0000-BADCAFFEE000", 2)] // for testing (version 2)
+    [StorableType("00000000-0000-0000-0000-BADCAFFEE001", 2)] // for testing (version 2)
     private class V2 : NewBaseType {
       [Storable]
@@ -2189,5 +2189,5 @@
     }
 
-    [StorableType("00000000-0000-0000-0000-BADCAFFEE200", 3)] // for testing (version 3)
+    [StorableType("00000000-0000-0000-0000-BADCAFFEE002", 3)] // for testing (version 3)
     private class V3 : NewBaseType {
       [Storable]
@@ -2215,18 +2215,18 @@
       private static Dictionary<string, object> ConvertV1(Dictionary<string, object> values) {
         var newValues = new Dictionary<string, object>();
-        var items = (ItemCollection<IItem>)values["OldBaseType.items"];
-        newValues["NewBaseType.items"] = items.Select(iv => new DoubleValue((double)(((dynamic)iv).Value))).ToArray();
-        newValues["V2.a"] = ((IntValue)values["V1.a"]).Value;
-        newValues["V2.val"] = ((ItemList<IntValue>)values["V1.vals"]).Select(iv => iv.Value).ToArray();
-
-        newValues["V2.mySelf"] = values["V1.mySelf"]; // myself type will be mapped correctly
-
-        var tup = (Tuple<int, int>)values["V1.tup"];
+        var items = (ItemCollection<IItem>)values["F9F51075-490C-48E3-BF64-14514A210149.items"];
+        newValues["B72C58C8-3321-4706-AA94-578F57337070.items"] = items.Select(iv => new DoubleValue((double)(((dynamic)iv).Value))).ToArray();
+        newValues["D211A828-6440-4E72-A8C7-AA4F9B4FFA75.a"] = ((IntValue)values["D211A828-6440-4E72-A8C7-AA4F9B4FFA75.a"]).Value;
+        newValues["D211A828-6440-4E72-A8C7-AA4F9B4FFA75.val"] = ((ItemList<IntValue>)values["D211A828-6440-4E72-A8C7-AA4F9B4FFA75.vals"]).Select(iv => iv.Value).ToArray();
+
+        newValues["D211A828-6440-4E72-A8C7-AA4F9B4FFA75.mySelf"] = values["D211A828-6440-4E72-A8C7-AA4F9B4FFA75.mySelf"]; // myself type will be mapped correctly
+
+        var tup = (Tuple<int, int>)values["D211A828-6440-4E72-A8C7-AA4F9B4FFA75.tup"];
         if (tup != null) {
-          newValues["V2.TupItem1"] = tup.Item1;
-          newValues["V2.TupItem2"] = tup.Item2;
+          newValues["D211A828-6440-4E72-A8C7-AA4F9B4FFA75.TupItem1"] = tup.Item1;
+          newValues["D211A828-6440-4E72-A8C7-AA4F9B4FFA75.TupItem2"] = tup.Item2;
         }
 
-        newValues["V2.coords"] = new Point((int)values["V1.x"], (int)values["V1.y"]);
+        newValues["D211A828-6440-4E72-A8C7-AA4F9B4FFA75.coords"] = new Point((int)values["D211A828-6440-4E72-A8C7-AA4F9B4FFA75.x"], (int)values["D211A828-6440-4E72-A8C7-AA4F9B4FFA75.y"]);
 
         return newValues;
@@ -2236,11 +2236,10 @@
       private static Dictionary<string, object> ConvertV2(Dictionary<string, object> values) {
         var newValues = new Dictionary<string, object>();
-        newValues["NewBaseType.items"] = values["NewBaseType.items"];
-        newValues["V3.a"] = values["V2.a"];
-        newValues["V3.val"] = values["V2.val"];
-        newValues["V3.mySelf"] = values["V2.mySelf"];
-
-        newValues["V3.tup"] = Tuple.Create((int)values["V2.TupItem1"], (int)values["V2.TupItem2"]);
-        newValues["V3.coords"] = values["V2.coords"];
+        newValues["D211A828-6440-4E72-A8C7-AA4F9B4FFA75.a"] = values["D211A828-6440-4E72-A8C7-AA4F9B4FFA75.a"];
+        newValues["D211A828-6440-4E72-A8C7-AA4F9B4FFA75.val"] = values["D211A828-6440-4E72-A8C7-AA4F9B4FFA75.val"];
+        newValues["D211A828-6440-4E72-A8C7-AA4F9B4FFA75.mySelf"] = values["D211A828-6440-4E72-A8C7-AA4F9B4FFA75.mySelf"];
+
+        newValues["D211A828-6440-4E72-A8C7-AA4F9B4FFA75.tup"] = Tuple.Create((int)values["D211A828-6440-4E72-A8C7-AA4F9B4FFA75.TupItem1"], (int)values["D211A828-6440-4E72-A8C7-AA4F9B4FFA75.TupItem2"]);
+        newValues["D211A828-6440-4E72-A8C7-AA4F9B4FFA75.coords"] = values["D211A828-6440-4E72-A8C7-AA4F9B4FFA75.coords"];
 
         return newValues;
@@ -2270,11 +2269,17 @@
       Mapper.StaticCache.DeregisterType(StorableTypeAttribute.GetStorableTypeAttribute(typeof(V2)).Guid);
       Mapper.StaticCache.DeregisterType(StorableTypeAttribute.GetStorableTypeAttribute(typeof(V3)).Guid);
-
       Mapper.StaticCache.RegisterType(StorableTypeAttribute.GetStorableTypeAttribute(typeof(V1)).Guid, typeof(V3));
-      var pi = typeof(StorableTypeAttribute).GetProperty("Guid");
-      pi.SetValue(
-        Mapper.StaticCache.GetTypeInfo(typeof(V3)).StorableTypeAttribute,
-        StorableTypeAttribute.GetStorableTypeAttribute(typeof(V1)).Guid,
-        null);
+
+      var typeInfosField = typeof(StaticCache).GetField("typeInfos", BindingFlags.NonPublic | BindingFlags.Instance);
+      var typeInfos = (Dictionary<Type, Persistence.TypeInfo>)typeInfosField.GetValue(Mapper.StaticCache);
+
+      var guidPI = typeof(StorableTypeAttribute).GetProperty("Guid");
+      var convPI = typeof(Persistence.TypeInfo).GetProperty("ConversionMethods");
+
+      var oldBInfo = typeInfos[typeof(V1)];
+      var newBInfo = Mapper.StaticCache.GetTypeInfo(typeof(V3));
+      guidPI.SetValue(newBInfo.StorableTypeAttribute, oldBInfo.StorableTypeAttribute.Guid);
+      //convPI.SetValue(newBInfo, oldBInfo.ConversionMethods);
+      typeInfos.Remove(typeof(V1));
 
       object o = serializer.Deserialize(tempFile);
@@ -2348,10 +2353,104 @@
           serializer.Serialize(original, fileName + ".proto");
           // var newVersion = serializer.Deserialize(fileName + ".proto");
-          Console.WriteLine("File: " + fileName);
-          var p = Profile(() => original);
+          //Console.WriteLine("File: " + fileName);
+          var p = Profile(() => original, Path.GetFileName(fileName));
           Console.WriteLine(p);
         }
       }
     }
+
+    [StorableType("3B48A44F-93E2-4ECC-A9B9-56E425EF96F8")]
+    private class ConversionA {
+      [Storable]
+      public int f;
+    }
+
+    [StorableType("00000000-0000-0000-0000-000000000002", 2)]
+    private class ConversionANew {
+      [Storable]
+      public int g;
+    }
+
+    [StorableType("7CBF2251-CF9F-4D9E-AA7B-C65495AE078F")]
+    private class ConversionB : ConversionA {
+      [Storable]
+      public int f;
+      public int BaseF { get { return base.f; } }
+
+      public ConversionB() {
+
+      }
+
+      public ConversionB(int myF, int baseF) {
+        this.f = myF;
+        base.f = baseF;
+      }
+    }
+
+    [StorableType("00000000-0000-0000-0000-000000000001", 2)]
+    private class ConversionBNew : ConversionANew {
+      [Storable]
+      public int g;
+
+      public int BaseG { get { return base.g; } }
+    }
+
+    private static class NewConversions {
+      [StorableConversion("7CBF2251-CF9F-4D9E-AA7B-C65495AE078F", 1)]
+      private static Dictionary<string, object> ConvertB(Dictionary<string, object> values) {
+        var newValues = new Dictionary<string, object>();
+        newValues["7CBF2251-CF9F-4D9E-AA7B-C65495AE078F.g"] = values["7CBF2251-CF9F-4D9E-AA7B-C65495AE078F.f"];
+        return newValues;
+      }
+
+      [StorableConversion("3B48A44F-93E2-4ECC-A9B9-56E425EF96F8", 1)]
+      private static Dictionary<string, object> ConvertA(Dictionary<string, object> values) {
+        var newValues = new Dictionary<string, object>();
+        newValues["3B48A44F-93E2-4ECC-A9B9-56E425EF96F8.g"] = values["3B48A44F-93E2-4ECC-A9B9-56E425EF96F8.f"];
+        return newValues;
+      }
+    }
+
+    [TestMethod]
+    [TestCategory("Persistence4")]
+    [TestProperty("Time", "short")]
+    public void TestConversionCase1() {
+      var test = new Func<ConversionB>(() => {
+        return new ConversionB(1, 2);
+      });
+
+      ProtoBufSerializer serializer = new ProtoBufSerializer();
+      var old = test();
+      serializer.Serialize(old, tempFile);
+      Mapper.StaticCache.DeregisterType(StorableTypeAttribute.GetStorableTypeAttribute(typeof(ConversionB)).Guid);
+      Mapper.StaticCache.DeregisterType(StorableTypeAttribute.GetStorableTypeAttribute(typeof(ConversionBNew)).Guid);
+      Mapper.StaticCache.DeregisterType(StorableTypeAttribute.GetStorableTypeAttribute(typeof(ConversionA)).Guid);
+      Mapper.StaticCache.DeregisterType(StorableTypeAttribute.GetStorableTypeAttribute(typeof(ConversionANew)).Guid);
+      Mapper.StaticCache.RegisterType(StorableTypeAttribute.GetStorableTypeAttribute(typeof(ConversionB)).Guid, typeof(ConversionBNew));
+      Mapper.StaticCache.RegisterType(StorableTypeAttribute.GetStorableTypeAttribute(typeof(ConversionA)).Guid, typeof(ConversionANew));
+
+      var typeInfosField = typeof(StaticCache).GetField("typeInfos", BindingFlags.NonPublic | BindingFlags.Instance);
+      var typeInfos = (Dictionary<Type, Persistence.TypeInfo>)typeInfosField.GetValue(Mapper.StaticCache);
+
+      var guidPI = typeof(StorableTypeAttribute).GetProperty("Guid");
+      var convPI = typeof(Persistence.TypeInfo).GetProperty("ConversionMethods");
+
+      var oldAInfo = typeInfos[typeof(ConversionA)];
+      var newAInfo = Mapper.StaticCache.GetTypeInfo(typeof(ConversionANew));
+      guidPI.SetValue(newAInfo.StorableTypeAttribute, oldAInfo.StorableTypeAttribute.Guid);
+      //convPI.SetValue(newAInfo, oldAInfo.ConversionMethods);
+      typeInfos.Remove(typeof(ConversionA));
+
+      var oldBInfo = typeInfos[typeof(ConversionB)];
+      var newBInfo = Mapper.StaticCache.GetTypeInfo(typeof(ConversionBNew));
+      guidPI.SetValue(newBInfo.StorableTypeAttribute, oldBInfo.StorableTypeAttribute.Guid);
+      //convPI.SetValue(newBInfo, oldBInfo.ConversionMethods);
+      typeInfos.Remove(typeof(ConversionB));
+
+      object o = serializer.Deserialize(tempFile);
+      var restored = (ConversionBNew)o;
+      Assert.AreEqual(restored.g, old.f);
+      Assert.AreEqual(restored.BaseG, old.BaseF);
+    }
   }
 }
