- Timestamp:
- 04/28/10 11:33:38 (15 years ago)
- Location:
- trunk/sources/HeuristicLab.Persistence/3.3/Default/CompositeSerializers/Storable
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/sources/HeuristicLab.Persistence/3.3/Default/CompositeSerializers/Storable/StorableReflection.cs
r3205 r3553 7 7 using HeuristicLab.Persistence.Auxiliary; 8 8 using System.Text; 9 using System.Reflection.Emit; 9 10 10 11 namespace HeuristicLab.Persistence.Default.CompositeSerializers.Storable { … … 18 19 BindingFlags.DeclaredOnly; 19 20 20 public static IEnumerable<StorableMemberInfo> GenerateStorableMembers(Type type, bool inherited) { 21 private delegate void HookWrapper<T>(T o); 22 public delegate void Hook(object o); 23 24 public static IEnumerable<StorableMemberInfo> GenerateStorableMembers(Type type) { 21 25 var storableMembers = new List<StorableMemberInfo>(); 22 if ( inherited &&type.BaseType != null)23 storableMembers.AddRange(GenerateStorableMembers(type.BaseType , true));26 if (type.BaseType != null) 27 storableMembers.AddRange(GenerateStorableMembers(type.BaseType)); 24 28 25 29 var storableClassAttribute = GetStorableClassAttribute(type); … … 47 51 } 48 52 49 public static IEnumerable< MethodInfo> CollectHooks(HookType hookType, Type type) {53 public static IEnumerable<Hook> CollectHooks(HookType hookType, Type type) { 50 54 if (type.BaseType != null) 51 55 foreach (var mi in CollectHooks(hookType, type.BaseType)) … … 56 60 MethodInfo methodInfo = memberInfo as MethodInfo; 57 61 if (memberInfo.MemberType != MemberTypes.Method || memberInfo == null) 58 throw new ArgumentException("Storable hooks must be methods"); 59 yield return methodInfo; 62 throw new ArgumentException("Storable hooks must be methods"); 63 DynamicMethod dm = new DynamicMethod("", null, new[] { typeof(object) }, type); 64 ILGenerator ilgen = dm.GetILGenerator(); 65 ilgen.Emit(OpCodes.Ldarg_1); 66 ilgen.Emit(OpCodes.Call, methodInfo); 67 ilgen.Emit(OpCodes.Ret); 68 yield return (Hook)dm.CreateDelegate(typeof(Hook)); 60 69 } 61 70 } -
trunk/sources/HeuristicLab.Persistence/3.3/Default/CompositeSerializers/Storable/StorableSerializer.cs
r3036 r3553 7 7 using HeuristicLab.Persistence.Auxiliary; 8 8 using System.Text; 9 using System.Reflection.Emit; 9 10 10 11 namespace HeuristicLab.Persistence.Default.CompositeSerializers.Storable { … … 38 39 /// </returns> 39 40 public bool CanSerialize(Type type) { 40 if (!ReflectionTools.HasDefaultConstructor(type) && 41 GetStorableConstructor(type) == null) 41 if (GetConstructor(type) == null) 42 42 return false; 43 43 return StorableReflection.IsEmptyOrStorableType(type, true); … … 53 53 /// </returns> 54 54 public string JustifyRejection(Type type) { 55 if (!ReflectionTools.HasDefaultConstructor(type) && 56 GetStorableConstructor(type) == null) 55 if (GetConstructor(type) == null) 57 56 return "no default constructor and no storable constructor"; 58 57 if (!StorableReflection.IsEmptyOrStorableType(type, true)) … … 84 83 } 85 84 86 private static readonly object[] defaultArgs = new object[] { true };87 88 85 /// <summary> 89 86 /// Create an instance of the object using the provided meta information. … … 94 91 public object CreateInstance(Type type, IEnumerable<Tag> metaInfo) { 95 92 try { 96 ConstructorInfo constructor = GetStorableConstructor(type); 97 return constructor != null ? constructor.Invoke(defaultArgs) : Activator.CreateInstance(type, true); 93 return GetConstructor(type)(); 98 94 } catch (TargetInvocationException x) { 99 95 throw new PersistenceException( … … 134 130 private static readonly object[] emptyArgs = new object[] { }; 135 131 136 private sealed class TypeQuery{132 private sealed class HookDesignator { 137 133 public Type Type { get; private set; } 138 public bool Inherited { get; private set; } 139 public TypeQuery(Type type, bool inherited) { 140 this.Type = type; 141 this.Inherited = inherited; 142 } 143 } 144 145 private sealed class HookDesignator { 146 public Type Type { get; set; } 147 public HookType HookType { get; set; } 134 public HookType HookType { get; private set; } 148 135 public HookDesignator() { } 149 136 public HookDesignator(Type type, HookType hookType) { … … 153 140 } 154 141 155 private sealed class MemberCache : Dictionary<Type Query, IEnumerable<StorableMemberInfo>> { }142 private sealed class MemberCache : Dictionary<Type, IEnumerable<StorableMemberInfo>> { } 156 143 157 144 #endregion … … 160 147 161 148 private MemberCache storableMemberCache = new MemberCache(); 162 private Dictionary<Type, ConstructorInfo> constructorCache = 163 new Dictionary<Type, ConstructorInfo>(); 164 165 private Dictionary<HookDesignator, List<MethodInfo>> hookCache = 166 new Dictionary<HookDesignator, List<MethodInfo>>(); 149 150 private delegate object Constructor(); 151 152 private Dictionary<Type, Constructor> constructorCache = 153 new Dictionary<Type, Constructor>(); 154 155 private Dictionary<HookDesignator, List<StorableReflection.Hook>> hookCache = 156 new Dictionary<HookDesignator, List<StorableReflection.Hook>>(); 167 157 168 158 #endregion … … 171 161 172 162 private IEnumerable<StorableMemberInfo> GetStorableMembers(Type type) { 173 return GetStorableMembers(type, true);174 }175 176 private IEnumerable<StorableMemberInfo> GetStorableMembers(Type type, bool inherited) {177 163 lock (storableMemberCache) { 178 var query = new TypeQuery(type, inherited); 179 if (storableMemberCache.ContainsKey(query)) 180 return storableMemberCache[query]; 181 var storablesMembers = StorableReflection.GenerateStorableMembers(type, inherited); 182 storableMemberCache[query] = storablesMembers; 164 if (storableMemberCache.ContainsKey(type)) 165 return storableMemberCache[type]; 166 var storablesMembers = StorableReflection.GenerateStorableMembers(type); 167 storableMemberCache[type] = storablesMembers; 183 168 return storablesMembers; 184 169 } 185 } 186 187 private Constructor Info GetStorableConstructor(Type type) {170 } 171 172 private Constructor GetConstructor(Type type) { 188 173 lock (constructorCache) { 189 174 if (constructorCache.ContainsKey(type)) 190 175 return constructorCache[type]; 191 foreach (ConstructorInfo ci in type.GetConstructors(ALL_CONSTRUCTORS)) { 192 if (ci.GetCustomAttributes(typeof(StorableConstructorAttribute), false).Length > 0) { 193 if (ci.GetParameters().Length != 1 || 194 ci.GetParameters()[0].ParameterType != typeof(bool)) 195 throw new PersistenceException("StorableConstructor must have exactly one argument of type bool"); 196 constructorCache[type] = ci; 197 return ci; 198 } 176 Constructor c = FindStorableConstructor(type) ?? GetDefaultConstructor(type); 177 constructorCache.Add(type, c); 178 return c; 179 } 180 } 181 182 private Constructor GetDefaultConstructor(Type type) { 183 ConstructorInfo ci = type.GetConstructor(ALL_CONSTRUCTORS, null, Type.EmptyTypes, null); 184 if (ci == null) 185 return null; 186 DynamicMethod dm = new DynamicMethod("", typeof(object), null, type); 187 ILGenerator ilgen = dm.GetILGenerator(); 188 ilgen.Emit(OpCodes.Newobj, ci); 189 ilgen.Emit(OpCodes.Ret); 190 return (Constructor)dm.CreateDelegate(typeof(Constructor)); 191 } 192 193 private Constructor FindStorableConstructor(Type type) { 194 foreach (ConstructorInfo ci in type.GetConstructors(ALL_CONSTRUCTORS)) { 195 if (ci.GetCustomAttributes(typeof(StorableConstructorAttribute), false).Length > 0) { 196 if (ci.GetParameters().Length != 1 || 197 ci.GetParameters()[0].ParameterType != typeof(bool)) 198 throw new PersistenceException("StorableConstructor must have exactly one argument of type bool"); 199 DynamicMethod dm = new DynamicMethod("", typeof(object), null, type); 200 ILGenerator ilgen = dm.GetILGenerator(); 201 ilgen.Emit(OpCodes.Ldc_I4_1); // load true 202 ilgen.Emit(OpCodes.Newobj, ci); 203 ilgen.Emit(OpCodes.Ret); 204 return (Constructor)dm.CreateDelegate(typeof(Constructor)); 199 205 } 200 constructorCache[type] = null; 201 return null; 202 } 206 } 207 return null; 203 208 } 204 209 … … 211 216 if (obj == null) 212 217 throw new ArgumentNullException("Cannot invoke hooks on null"); 213 foreach ( MethodInfo miin GetHooks(hookType, obj.GetType())) {214 mi.Invoke(obj, emptyArgs);215 } 216 } 217 218 private IEnumerable< MethodInfo> GetHooks(HookType hookType, Type type) {218 foreach (StorableReflection.Hook hook in GetHooks(hookType, obj.GetType())) { 219 hook(obj); 220 } 221 } 222 223 private IEnumerable<StorableReflection.Hook> GetHooks(HookType hookType, Type type) { 219 224 lock (hookCache) { 220 List< MethodInfo> hooks;225 List<StorableReflection.Hook> hooks; 221 226 var designator = new HookDesignator(type, hookType); 222 227 hookCache.TryGetValue(designator, out hooks); 223 228 if (hooks != null) 224 229 return hooks; 225 hooks = new List< MethodInfo>(StorableReflection.CollectHooks(hookType, type));230 hooks = new List<StorableReflection.Hook>(StorableReflection.CollectHooks(hookType, type)); 226 231 hookCache.Add(designator, hooks); 227 232 return hooks; … … 231 236 #endregion 232 237 233 234 238 239 235 240 } 236 241 237 242 }
Note: See TracChangeset
for help on using the changeset viewer.