Changeset 3913
- Timestamp:
- 06/09/10 16:29:02 (14 years ago)
- Location:
- trunk/sources/HeuristicLab.Persistence/3.3
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/sources/HeuristicLab.Persistence/3.3/Core/DataMemberAccessor.cs
r3743 r3913 23 23 using System.Reflection; 24 24 using HeuristicLab.Persistence.Core; 25 using System.Reflection.Emit; 26 using System.Collections.Generic; 25 27 26 28 namespace HeuristicLab.Persistence.Core { 27 29 28 30 /// <summary> 29 31 /// Encapsulation and abstraction for access a data member of an object … … 31 33 /// default value and an alternate name can be specified. 32 34 /// </summary> 33 public class DataMemberAccessor { 35 public sealed class DataMemberAccessor { 36 37 #region fields 34 38 35 39 /// <summary> 36 40 /// The function to get the value of the data member. 37 41 /// </summary> 38 public readonly Func<object > Get;42 public readonly Func<object, object> Get; 39 43 40 44 /// <summary> 41 45 /// The function to set the value of the data member. 42 46 /// </summary> 43 public readonly Action<object > Set;47 public readonly Action<object, object> Set; 44 48 45 49 /// <summary> … … 55 59 public readonly object DefaultValue; 56 60 61 #endregion 62 63 #region constructors 57 64 58 65 /// <summary> … … 63 70 /// <param name="name">The name.</param> 64 71 /// <param name="defaultvalue">The defaultvalue.</param> 65 /// <param name="obj">The object.</param> 66 public DataMemberAccessor(MemberInfo memberInfo, string name, object defaultvalue, object obj) { 72 public DataMemberAccessor(MemberInfo memberInfo, string name, object defaultvalue) { 73 Get = GenerateGetter(memberInfo); 74 Set = GenerateSetter(memberInfo); 67 75 Name = name; 68 76 DefaultValue = defaultvalue; 69 if (memberInfo.MemberType == MemberTypes.Field) {70 FieldInfo fieldInfo = (FieldInfo)memberInfo;71 Get = () => fieldInfo.GetValue(obj);72 Set = value => fieldInfo.SetValue(obj, value);73 } else if (memberInfo.MemberType == MemberTypes.Property) {74 PropertyInfo propertyInfo = (PropertyInfo)memberInfo;75 if (!propertyInfo.CanRead || !propertyInfo.CanWrite) {76 throw new PersistenceException(77 "Storable properties must implement both a Get and a Set Accessor. ");78 }79 Get = () => propertyInfo.GetValue(obj, null);80 Set = value => propertyInfo.SetValue(obj, value, null);81 } else {82 throw new PersistenceException(83 "The Storable attribute can only be applied to fields and properties.");84 }85 }86 87 /// <summary>88 /// Wrap existing getter and setter functions.89 /// </summary>90 /// <param name="name">The name.</param>91 /// <param name="defaultValue">The default value.</param>92 /// <param name="getter">The getter.</param>93 /// <param name="setter">The setter.</param>94 public DataMemberAccessor(string name, object defaultValue,95 Func<object> getter, Action<object> setter) {96 Name = name;97 DefaultValue = defaultValue;98 Get = getter;99 Set = setter;100 77 } 101 78 … … 103 80 /// Create an empty accessor that just encapsulates an object 104 81 /// without access. 105 /// </summary> 106 /// <param name="o">The object</param> 107 public DataMemberAccessor(object o) { 82 /// </summary> 83 public DataMemberAccessor() { 108 84 Name = null; 109 85 DefaultValue = null; 110 Get = () => o; 111 Set = null; 86 Get = Id; 112 87 } 113 88 … … 115 90 /// Create an empty accessor that just encapsulates an object 116 91 /// without access. 117 /// </summary> 118 /// <param name="o">The object</param> 92 /// </summary> 119 93 /// <param name="name">The object's name.</param> 120 public DataMemberAccessor( object o,string name) {94 public DataMemberAccessor(string name) { 121 95 Name = name; 122 96 DefaultValue = null; 123 Get = () => o; 124 Set = null; 125 } 97 Get = Id; 98 } 99 100 /// <summary> 101 /// Initializes a new instance of the <see cref="DataMemberAccessor"/> class using the 102 /// getter and setter from an exisiting instance but with a new name and default value. 103 /// </summary> 104 /// <param name="dma">The existing DataMemberAccessor.</param> 105 /// <param name="name">The new name.</param> 106 /// <param name="defaultValue">The new default value.</param> 107 public DataMemberAccessor(DataMemberAccessor dma, string name, object defaultValue) { 108 Get = dma.Get; 109 Set = dma.Set; 110 this.Name = name; 111 this.DefaultValue = defaultValue; 112 } 113 114 #endregion 115 116 #region auxiliary methods 126 117 127 118 /// <summary> … … 137 128 Get.Method, Set.Method); 138 129 } 130 131 /// <summary> 132 /// The identity function 133 /// </summary> 134 /// <param name="o">An object.</param> 135 /// <returns>its argument o unmodified.</returns> 136 public static object Id(object o) { 137 return o; 138 } 139 140 #endregion 141 142 #region static methods (code generators) 143 144 /// <summary> 145 /// Generate a getter for the given field or property 146 /// </summary> 147 /// <param name="memberInfo">The member info.</param> 148 /// <returns></returns> 149 public static Func<object, object> GenerateGetter(MemberInfo memberInfo) { 150 if (memberInfo.MemberType == MemberTypes.Field) { 151 FieldInfo fieldInfo = (FieldInfo)memberInfo; 152 return GenerateFieldGetter(fieldInfo); 153 } else if (memberInfo.MemberType == MemberTypes.Property) { 154 PropertyInfo propertyInfo = (PropertyInfo)memberInfo; 155 if (!propertyInfo.CanRead || !propertyInfo.CanWrite) { 156 throw new PersistenceException( 157 "Storable properties must implement both a Get and a Set Accessor. "); 158 } 159 return GeneratePropertyGetter(propertyInfo); 160 } else { 161 throw new PersistenceException( 162 "The Storable attribute can only be applied to fields and properties."); 163 } 164 } 165 166 /// <summary> 167 /// Generates a setter for the given field or property. 168 /// </summary> 169 /// <param name="memberInfo">The member info.</param> 170 /// <returns></returns> 171 public static Action<object, object> GenerateSetter(MemberInfo memberInfo) { 172 if (memberInfo.MemberType == MemberTypes.Field) { 173 FieldInfo fieldInfo = (FieldInfo)memberInfo; 174 return GenerateFieldSetter(fieldInfo); 175 } else if (memberInfo.MemberType == MemberTypes.Property) { 176 PropertyInfo propertyInfo = (PropertyInfo)memberInfo; 177 if (!propertyInfo.CanRead || !propertyInfo.CanWrite) { 178 throw new PersistenceException( 179 "Storable properties must implement both a Get and a Set Accessor. "); 180 } 181 return GeneratePropertySetter(propertyInfo); 182 } else { 183 throw new PersistenceException( 184 "The Storable attribute can only be applied to fields and properties."); 185 } 186 } 187 188 /// <summary> 189 /// Generates a dynamically compiled getter to access fields (even private ones). 190 /// </summary> 191 /// <param name="fieldInfo">The field info.</param> 192 /// <returns>A Func<object, object></returns> 193 public static Func<object, object> GenerateFieldGetter(FieldInfo fieldInfo) { 194 DynamicMethod dm = new DynamicMethod("", typeof(object), new Type[] { typeof(object) }, fieldInfo.DeclaringType, true); 195 ILGenerator ilgen = dm.GetILGenerator(); 196 ilgen.Emit(OpCodes.Ldarg_0); 197 ilgen.Emit(OpCodes.Castclass, fieldInfo.DeclaringType); 198 ilgen.Emit(OpCodes.Ldfld, fieldInfo); 199 ilgen.Emit(OpCodes.Box, fieldInfo.FieldType); 200 ilgen.Emit(OpCodes.Ret); 201 return (Func<object, object>)dm.CreateDelegate(typeof(Func<object, object>)); 202 } 203 204 /// <summary> 205 /// Generates a dynamically compiled sett to access fields (even private ones). 206 /// </summary> 207 /// <param name="fieldInfo">The field info.</param> 208 /// <returns>An Action<object, object%gt;</returns> 209 public static Action<object, object> GenerateFieldSetter(FieldInfo fieldInfo) { 210 DynamicMethod dm = new DynamicMethod("", null, new Type[] { typeof(object), typeof(object) }, fieldInfo.DeclaringType, true); 211 ILGenerator ilgen = dm.GetILGenerator(); 212 ilgen.Emit(OpCodes.Ldarg_0); 213 ilgen.Emit(OpCodes.Castclass, fieldInfo.DeclaringType); 214 ilgen.Emit(OpCodes.Ldarg_1); 215 ilgen.Emit(OpCodes.Unbox_Any, fieldInfo.FieldType); 216 ilgen.Emit(OpCodes.Stfld, fieldInfo); 217 ilgen.Emit(OpCodes.Ret); 218 return (Action<object, object>)dm.CreateDelegate(typeof(Action<object, object>)); 219 } 220 221 /// <summary> 222 /// Generates a dynamically compiled getter to access properties (even private ones). 223 /// </summary> 224 /// <param name="propertyInfo">The property info.</param> 225 /// <returns>A Func<object, object></returns> 226 public static Func<object, object> GeneratePropertyGetter(PropertyInfo propertyInfo) { 227 DynamicMethod dm = new DynamicMethod("", typeof(object), new Type[] { typeof(object) }, propertyInfo.DeclaringType, true); 228 ILGenerator ilgen = dm.GetILGenerator(); 229 ilgen.Emit(OpCodes.Ldarg_0); 230 ilgen.Emit(OpCodes.Castclass, propertyInfo.DeclaringType); 231 ilgen.Emit(OpCodes.Callvirt, propertyInfo.GetGetMethod(true)); 232 ilgen.Emit(OpCodes.Box, propertyInfo.PropertyType); 233 ilgen.Emit(OpCodes.Ret); 234 return (Func<object, object>)dm.CreateDelegate(typeof(Func<object, object>)); 235 } 236 237 /// <summary> 238 /// Generates a dynamically compiled setter to access properties (even private ones). 239 /// </summary> 240 /// <param name="propertyInfo">The property info.</param> 241 /// <returns>An Action<object, object%gt;</returns> 242 public static Action<object, object> GeneratePropertySetter(PropertyInfo propertyInfo) { 243 DynamicMethod dm = new DynamicMethod("", null, new Type[] { typeof(object), typeof(object) }, propertyInfo.DeclaringType, true); 244 ILGenerator ilgen = dm.GetILGenerator(); 245 ilgen.Emit(OpCodes.Ldarg_0); 246 ilgen.Emit(OpCodes.Castclass, propertyInfo.DeclaringType); 247 ilgen.Emit(OpCodes.Ldarg_1); 248 ilgen.Emit(OpCodes.Unbox_Any, propertyInfo.PropertyType); 249 ilgen.Emit(OpCodes.Callvirt, propertyInfo.GetSetMethod(true)); 250 ilgen.Emit(OpCodes.Ret); 251 return (Action<object, object>)dm.CreateDelegate(typeof(Action<object, object>)); 252 } 253 254 #endregion 139 255 } 140 256 -
trunk/sources/HeuristicLab.Persistence/3.3/Core/Serializer.cs
r3743 r3913 187 187 /// </returns> 188 188 public IEnumerator<ISerializationToken> GetEnumerator() { 189 var enumerator = Serialize(new DataMemberAccessor(rootName , null, () => obj, null));189 var enumerator = Serialize(new DataMemberAccessor(rootName), obj); 190 190 if (isTestRun) { 191 191 return AddExceptionCompiler(enumerator); … … 206 206 private Stack<string> objectGraphTrace = new Stack<string>(); 207 207 208 private IEnumerator<ISerializationToken> Serialize(DataMemberAccessor accessor ) {208 private IEnumerator<ISerializationToken> Serialize(DataMemberAccessor accessor, object obj) { 209 209 210 object value = accessor.Get( );210 object value = accessor.Get(obj); 211 211 if (value == null) 212 212 return NullReferenceEnumerator(accessor.Name); … … 311 311 if (metaInfo != null) { 312 312 foreach (var tag in metaInfo) { 313 IEnumerator<ISerializationToken> metaIt = Serialize(new DataMemberAccessor(tag. Value, tag.Name));313 IEnumerator<ISerializationToken> metaIt = Serialize(new DataMemberAccessor(tag.Name), tag.Value); 314 314 while (metaIt.MoveNext()) { 315 315 if (first) { … … 326 326 if (tags != null) { 327 327 foreach (var tag in tags) { 328 IEnumerator<ISerializationToken> it = Serialize(new DataMemberAccessor(tag. Value, tag.Name));328 IEnumerator<ISerializationToken> it = Serialize(new DataMemberAccessor(tag.Name), tag.Value); 329 329 while (it.MoveNext()) 330 330 yield return it.Current; -
trunk/sources/HeuristicLab.Persistence/3.3/Default/CompositeSerializers/Storable/StorableReflection.cs
r3742 r3913 73 73 74 74 private static object[] emptyArgs = new object[0]; 75 private static Type[] objectArg = new[] { typeof(object) }; 75 76 76 77 public static IEnumerable<Hook> CollectHooks(HookType hookType, Type type) { … … 79 80 yield return mi; 80 81 foreach (MemberInfo memberInfo in type.GetMembers(DECLARED_INSTANCE_MEMBERS)) { 82 if (memberInfo.MemberType != MemberTypes.Method) 83 continue; 84 MethodInfo methodInfo = memberInfo as MethodInfo; 85 if (methodInfo.ReturnType != typeof(void)) 86 continue; 87 if (methodInfo.GetParameters().Length > 0) 88 continue; 81 89 foreach (StorableHookAttribute hook in memberInfo.GetCustomAttributes(typeof(StorableHookAttribute), false)) { 82 90 if (hook != null && hook.HookType == hookType) { 83 MethodInfo methodInfo = memberInfo as MethodInfo; 84 if (memberInfo.MemberType != MemberTypes.Method || memberInfo == null) 85 throw new ArgumentException("Storable hooks must be methods"); 86 DynamicMethod dm = new DynamicMethod("", null, new[] { typeof(object) }, type); 87 ILGenerator ilgen = dm.GetILGenerator(); 88 ilgen.Emit(OpCodes.Ldarg_0); 89 ilgen.Emit(OpCodes.Callvirt, methodInfo); 90 ilgen.Emit(OpCodes.Ret); 91 yield return (Hook)dm.CreateDelegate(typeof(Hook)); 91 yield return new Hook((o) => methodInfo.Invoke(o, emptyArgs)); 92 92 } 93 93 } … … 99 99 private static void AddMarkedMembers(Type type, List<StorableMemberInfo> storableMembers) { 100 100 foreach (MemberInfo memberInfo in type.GetMembers(DECLARED_INSTANCE_MEMBERS)) { 101 foreach (StorableAttribute attribute in memberInfo.GetCustomAttributes(typeof(StorableAttribute), false)) { 102 storableMembers.Add(new StorableMemberInfo(attribute, memberInfo)); 101 if (memberInfo.MemberType == MemberTypes.Field || 102 memberInfo.MemberType == MemberTypes.Property) { 103 foreach (StorableAttribute attribute in memberInfo.GetCustomAttributes(typeof(StorableAttribute), false)) { 104 storableMembers.Add(new StorableMemberInfo(attribute, memberInfo)); 105 } 103 106 } 104 107 } -
trunk/sources/HeuristicLab.Persistence/3.3/Default/CompositeSerializers/Storable/StorableSerializer.cs
r3742 r3913 109 109 /// <returns>An enumerable of <see cref="Tag"/>s.</returns> 110 110 public IEnumerable<Tag> Decompose(object obj) { 111 foreach (var accessor in GetStorableAccessors(obj )) {112 yield return new Tag(accessor.Name, accessor.Get( ));111 foreach (var accessor in GetStorableAccessors(obj.GetType())) { 112 yield return new Tag(accessor.Name, accessor.Get(obj)); 113 113 } 114 114 } … … 142 142 memberDict.Add(iter.Current.Name, iter.Current); 143 143 } 144 foreach (var accessor in GetStorableAccessors(instance )) {144 foreach (var accessor in GetStorableAccessors(instance.GetType())) { 145 145 if (memberDict.ContainsKey(accessor.Name)) { 146 accessor.Set( memberDict[accessor.Name].Value);146 accessor.Set(instance, memberDict[accessor.Name].Value); 147 147 } else if (accessor.DefaultValue != null) { 148 accessor.Set( accessor.DefaultValue);148 accessor.Set(instance, accessor.DefaultValue); 149 149 } 150 150 } … … 160 160 161 161 private static readonly object[] emptyArgs = new object[] { }; 162 private static readonly object[] trueArgs = new object[] { true }; 162 163 163 164 private sealed class HookDesignator { … … 171 172 } 172 173 173 private sealed class MemberCache : Dictionary<Type, IEnumerable<StorableMemberInfo>> { } 174 private sealed class AccessorListCache : Dictionary<Type, IEnumerable<DataMemberAccessor>> { } 175 private sealed class AccessorCache : Dictionary<MemberInfo, DataMemberAccessor> { } 174 176 175 177 #endregion … … 177 179 #region caches 178 180 179 private MemberCache storableMemberCache = new MemberCache(); 181 private AccessorListCache accessorListCache = new AccessorListCache(); 182 private AccessorCache accessorCache = new AccessorCache(); 180 183 181 184 private delegate object Constructor(); … … 191 194 #region attribute access 192 195 193 private IEnumerable<StorableMemberInfo> GetStorableMembers(Type type) { 194 lock (storableMemberCache) { 195 if (storableMemberCache.ContainsKey(type)) 196 return storableMemberCache[type]; 197 var storablesMembers = StorableReflection.GenerateStorableMembers(type); 198 storableMemberCache[type] = storablesMembers; 199 return storablesMembers; 196 private IEnumerable<DataMemberAccessor> GetStorableAccessors(Type type) { 197 lock (accessorListCache) { 198 if (accessorListCache.ContainsKey(type)) 199 return accessorListCache[type]; 200 var storableMembers = StorableReflection 201 .GenerateStorableMembers(type) 202 .Select(mi => GetMemberAccessor(mi)); 203 accessorListCache[type] = storableMembers; 204 return storableMembers; 205 } 206 } 207 208 private DataMemberAccessor GetMemberAccessor(StorableMemberInfo mi) { 209 lock (accessorCache) { 210 if (accessorCache.ContainsKey(mi.MemberInfo)) 211 return new DataMemberAccessor(accessorCache[mi.MemberInfo], mi.DisentangledName, mi.DefaultValue); 212 DataMemberAccessor dma = new DataMemberAccessor(mi.MemberInfo, mi.DisentangledName, mi.DefaultValue); 213 accessorCache[mi.MemberInfo] = dma; 214 return dma; 200 215 } 201 216 } … … 209 224 return c; 210 225 } 211 } 226 } 212 227 213 228 private Constructor GetDefaultConstructor(Type type) { 214 229 ConstructorInfo ci = type.GetConstructor(ALL_CONSTRUCTORS, null, Type.EmptyTypes, null); 215 230 if (ci == null) 216 return null; 231 return null; 217 232 DynamicMethod dm = new DynamicMethod("", typeof(object), null, type); 218 233 ILGenerator ilgen = dm.GetILGenerator(); … … 227 242 if (ci.GetParameters().Length != 1 || 228 243 ci.GetParameters()[0].ParameterType != typeof(bool)) 229 throw new PersistenceException("StorableConstructor must have exactly one argument of type bool"); 244 throw new PersistenceException("StorableConstructor must have exactly one argument of type bool"); 230 245 DynamicMethod dm = new DynamicMethod("", typeof(object), null, type); 231 246 ILGenerator ilgen = dm.GetILGenerator(); … … 237 252 } 238 253 return null; 239 } 240 241 private IEnumerable<DataMemberAccessor> GetStorableAccessors(object obj) { 242 return GetStorableMembers(obj.GetType()) 243 .Select(mi => new DataMemberAccessor(mi.MemberInfo, mi.DisentangledName, mi.DefaultValue, obj)); 244 } 254 } 245 255 246 256 private void InvokeHook(HookType hookType, object obj) { -
trunk/sources/HeuristicLab.Persistence/3.3/Default/Xml/Compact/DoubleList2XmlSerializer.cs
r3742 r3913 23 23 using System.Collections.Generic; 24 24 using System; 25 using System.Linq; 25 26 using HeuristicLab.Persistence.Core; 26 27 using HeuristicLab.Persistence.Default.Xml.Primitive; 28 using System.Text; 27 29 28 30 namespace HeuristicLab.Persistence.Default.Xml.Compact { 29 31 30 internal sealed class DoubleList2XmlSerializer : NumberEnumeration2XmlSerializerBase<List<double>> {32 internal sealed class DoubleList2XmlSerializer : CompactXmlSerializerBase<List<double>> { 31 33 32 protected override void Add(IEnumerable enumeration, object o) { 33 ((List<double>)enumeration).Add((double)o); 34 private static readonly char[] separators = new char[] { ';' }; 35 36 public override XmlString Format(List<double> list) { 37 StringBuilder sb = new StringBuilder(); 38 foreach (var d in list) { 39 sb.Append(Double2XmlSerializer.FormatG17(d)).Append(';'); 40 } 41 return new XmlString(sb.ToString()); 34 42 } 35 43 36 protected override IEnumerable Instantiate() { 37 return new List<double>(); 44 public override List<double> Parse(XmlString data) { 45 try { 46 var values = data.Data.Split(separators, StringSplitOptions.RemoveEmptyEntries); 47 List<double> list = new List<double>(values.Length); 48 foreach (var value in values) { 49 list.Add(Double2XmlSerializer.ParseG17(value)); 50 } 51 return list; 52 } catch (InvalidCastException e) { 53 throw new PersistenceException("Invalid element data during reconstruction of List<double>.", e); 54 } catch (OverflowException e) { 55 throw new PersistenceException("Overflow during element parsing while trying to reconstruct List<double>.", e); 56 } 38 57 } 39 40 protected override string FormatValue(object o) {41 return Double2XmlSerializer.FormatG17((double)o);42 }43 44 protected override object ParseValue(string o) {45 return Double2XmlSerializer.ParseG17(o);46 }47 48 58 } 49 59 } -
trunk/sources/HeuristicLab.Persistence/3.3/Default/Xml/XmlParser.cs
r3742 r3913 188 188 /// <returns>A fresh object instance</returns> 189 189 public static object Deserialize(string filename) { 190 using (ZipFile file = new ZipFile(filename)) { 191 return Deserialize(file); 190 TimeSpan start = System.Diagnostics.Process.GetCurrentProcess().TotalProcessorTime; 191 try { 192 using (ZipFile file = new ZipFile(filename)) { 193 return Deserialize(file); 194 } 195 } finally { 196 TimeSpan end = System.Diagnostics.Process.GetCurrentProcess().TotalProcessorTime; 197 Tracing.Logger.Info(string.Format( 198 "deserialization of {0} took {1} seconds", 199 filename, (end - start).TotalSeconds)); 192 200 } 193 201 }
Note: See TracChangeset
for help on using the changeset viewer.