Index: /trunk/sources/HeuristicLab.Persistence/3.3/Default/CompositeSerializers/Storable/StorableHookAttribute.cs
===================================================================
--- /trunk/sources/HeuristicLab.Persistence/3.3/Default/CompositeSerializers/Storable/StorableHookAttribute.cs	(revision 2980)
+++ /trunk/sources/HeuristicLab.Persistence/3.3/Default/CompositeSerializers/Storable/StorableHookAttribute.cs	(revision 2980)
@@ -0,0 +1,46 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Reflection;
+
+namespace HeuristicLab.Persistence.Default.CompositeSerializers.Storable {
+
+  public enum HookType { BeforeSerialization, AfterDeserialization };
+
+  [AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)]
+  public sealed class StorableHookAttribute : Attribute {
+
+    private readonly HookType hookType;
+    public HookType HookType {
+      get { return hookType; }
+    }
+
+    public StorableHookAttribute(HookType hookType) {
+      this.hookType = hookType;
+    }
+
+    private static readonly BindingFlags instanceMembers =
+      BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public;
+
+    private static readonly object[] emptyArgs = new object[] { };
+
+    public static void InvokeHook(HookType hookType, object obj) {
+      if (obj == null)
+        throw new ArgumentNullException("Cannot invoke hooks on null");
+      Type type = obj.GetType();
+      foreach (MemberInfo memberInfo in type.GetMembers(instanceMembers)) {
+        foreach (object attribute in memberInfo.GetCustomAttributes(false)) {
+          StorableHookAttribute hook = attribute as StorableHookAttribute;
+          if (hook != null && hook.HookType == hookType) {
+            MethodInfo methodInfo = memberInfo as MethodInfo;
+            if (memberInfo.MemberType != MemberTypes.Method || memberInfo == null)
+              throw new ArgumentException("Storable hooks must be methods");            
+            methodInfo.Invoke(obj, emptyArgs);            
+          }
+        }
+      }
+    }
+
+  }
+}
Index: /trunk/sources/HeuristicLab.Persistence/3.3/Default/CompositeSerializers/Storable/StorableSerializer.cs
===================================================================
--- /trunk/sources/HeuristicLab.Persistence/3.3/Default/CompositeSerializers/Storable/StorableSerializer.cs	(revision 2979)
+++ /trunk/sources/HeuristicLab.Persistence/3.3/Default/CompositeSerializers/Storable/StorableSerializer.cs	(revision 2980)
@@ -29,4 +29,5 @@
 
     public IEnumerable<Tag> CreateMetaInfo(object o) {
+      StorableHookAttribute.InvokeHook(HookType.BeforeSerialization, o);
       return new Tag[] { };
     }
@@ -48,11 +49,12 @@
         memberDict.Add(iter.Current.Name, iter.Current);
       }
-      foreach (var accessor in StorableAttribute.GetStorableAccessors(instance)) {        
+      foreach (var accessor in StorableAttribute.GetStorableAccessors(instance)) {
         if (memberDict.ContainsKey(accessor.Name)) {
-          accessor.Set(memberDict[accessor.Name].Value);          
+          accessor.Set(memberDict[accessor.Name].Value);
         } else if (accessor.DefaultValue != null) {
-          accessor.Set(accessor.DefaultValue);          
+          accessor.Set(accessor.DefaultValue);
         }
       }
+      StorableHookAttribute.InvokeHook(HookType.AfterDeserialization, instance);
     }
   }
Index: /trunk/sources/HeuristicLab.Persistence/3.3/HeuristicLab.Persistence-3.3.csproj
===================================================================
--- /trunk/sources/HeuristicLab.Persistence/3.3/HeuristicLab.Persistence-3.3.csproj	(revision 2979)
+++ /trunk/sources/HeuristicLab.Persistence/3.3/HeuristicLab.Persistence-3.3.csproj	(revision 2980)
@@ -121,4 +121,5 @@
     <Compile Include="Default\CompositeSerializers\Storable\EmptyStorableClassAttribute.cs" />
     <Compile Include="Default\CompositeSerializers\Storable\StorableAttribute.cs" />
+    <Compile Include="Default\CompositeSerializers\Storable\StorableHookAttribute.cs" />
     <Compile Include="Default\CompositeSerializers\Storable\StorableSerializer.cs" />
     <Compile Include="Default\CompositeSerializers\StructSerializer.cs" />
Index: /trunk/sources/HeuristicLab.Persistence/3.3/Tests/UseCases.cs
===================================================================
--- /trunk/sources/HeuristicLab.Persistence/3.3/Tests/UseCases.cs	(revision 2979)
+++ /trunk/sources/HeuristicLab.Persistence/3.3/Tests/UseCases.cs	(revision 2980)
@@ -659,4 +659,38 @@
     }
 
+    private class PersistenceHooks {
+      [Storable]
+      public int a;
+      [Storable]
+      public int b;
+      public int sum;
+      public bool WasSerialized { get; private set; }
+      [StorableHook(HookType.BeforeSerialization)]
+      void PreSerializationHook() {
+        WasSerialized = true;
+      }
+      [StorableHook(HookType.AfterDeserialization)]
+      void PostDeserializationHook() {
+        sum = a + b;
+      }
+    }
+
+    [TestMethod]
+    public void HookTest() {
+      PersistenceHooks hookTest = new PersistenceHooks();
+      hookTest.a = 2;
+      hookTest.b = 5;
+      Assert.IsFalse(hookTest.WasSerialized);
+      Assert.AreEqual(hookTest.sum, 0);
+      XmlGenerator.Serialize(hookTest, tempFile);
+      Assert.IsTrue(hookTest.WasSerialized);
+      Assert.AreEqual(hookTest.sum, 0);
+      PersistenceHooks newHookTest = (PersistenceHooks)XmlParser.Deserialize(tempFile);
+      Assert.AreEqual(newHookTest.a, hookTest.a);
+      Assert.AreEqual(newHookTest.b, hookTest.b);
+      Assert.AreEqual(newHookTest.sum, newHookTest.a + newHookTest.b);
+      Assert.IsFalse(newHookTest.WasSerialized);
+    }
+
     [ClassInitialize]
     public static void Initialize(TestContext testContext) {
