Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Persistence/3.3/Default/CompositeSerializers/Storable/StorableHookAttribute.cs @ 2991

Last change on this file since 2991 was 2991, checked in by epitzer, 14 years ago

add caches for hooks (#900)

File size: 2.6 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5using System.Reflection;
6
7namespace HeuristicLab.Persistence.Default.CompositeSerializers.Storable {
8
9  public enum HookType { BeforeSerialization, AfterDeserialization };
10
11  [AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)]
12  public sealed class StorableHookAttribute : Attribute {
13
14    private sealed class HookDesignator {
15      public Type Type { get; set; }
16      public HookType HookType { get; set; }
17      public HookDesignator() { }
18      public HookDesignator(Type type, HookType hookType) {
19        Type = type;
20        HookType = HookType;
21      }
22    }
23
24    private readonly HookType hookType;
25    public HookType HookType {
26      get { return hookType; }
27    }
28
29    public StorableHookAttribute(HookType hookType) {
30      this.hookType = hookType;
31    }
32
33    private static readonly BindingFlags instanceMembers =
34      BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public;
35
36    private static readonly object[] emptyArgs = new object[] { };
37
38    private static Dictionary<HookDesignator, List<MethodInfo>> hookCache =
39      new Dictionary<HookDesignator, List<MethodInfo>>();
40
41    public static void InvokeHook(HookType hookType, object obj) {
42      if (obj == null)
43        throw new ArgumentNullException("Cannot invoke hooks on null");
44      foreach (MethodInfo mi in GetHooks(hookType, obj.GetType())) {
45        mi.Invoke(obj, emptyArgs);
46      }
47    }
48
49    private static IEnumerable<MethodInfo> GetHooks(HookType hookType, Type type) {
50      lock (hookCache) {
51        List<MethodInfo> hooks;
52        var designator = new HookDesignator(type, hookType);
53        hookCache.TryGetValue(designator, out hooks);
54        if (hooks != null)
55          return hooks;
56        hooks = new List<MethodInfo>(CollectHooks(hookType, type));
57        hookCache.Add(designator, hooks);
58        return hooks;
59      }
60    }
61
62    private static IEnumerable<MethodInfo> CollectHooks(HookType hookType, Type type) {     
63      foreach (MemberInfo memberInfo in type.GetMembers(instanceMembers)) {
64        foreach (StorableHookAttribute hook in memberInfo.GetCustomAttributes(typeof(StorableHookAttribute), false)) {
65          if (hook != null && hook.HookType == hookType) {
66            MethodInfo methodInfo = memberInfo as MethodInfo;
67            if (memberInfo.MemberType != MemberTypes.Method || memberInfo == null)
68              throw new ArgumentException("Storable hooks must be methods");
69            yield return methodInfo;
70          }
71        }
72      }
73    }
74
75  }
76}
Note: See TracBrowser for help on using the repository browser.