Changeset 15034
- Timestamp:
- 06/16/17 11:32:56 (7 years ago)
- Location:
- branches/PersistenceReintegration
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/PersistenceReintegration/HeuristicLab.Persistence/4.0/Core/StorableConversionAttribute.cs
r14927 r15034 26 26 [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)] 27 27 public sealed class StorableConversionAttribute : Attribute { 28 public uint SrcVersion { get; set; } 28 public Guid Guid { get; private set; } 29 public uint SrcVersion { get; private set; } 29 30 30 public StorableConversionAttribute(uint srcVersion) { 31 public StorableConversionAttribute(string guid, uint srcVersion) { 32 this.Guid = new Guid(guid); 31 33 this.SrcVersion = srcVersion; 32 34 } … … 35 37 return Attribute.IsDefined(mi, typeof(StorableConversionAttribute), false); 36 38 } 37 public static StorableConversionAttribute GetTransformerAttribute(MethodInfo mi) { 39 40 public static StorableConversionAttribute GetStorableConversionAttribute(MethodInfo mi) { 38 41 return (StorableConversionAttribute)Attribute.GetCustomAttribute(mi, typeof(StorableConversionAttribute), false); 39 42 } 43 public static Guid GetGuid(MethodInfo mi) { 44 return GetStorableConversionAttribute(mi).Guid; 45 } 40 46 public static uint GetVersion(MethodInfo mi) { 41 return Get TransformerAttribute(mi).SrcVersion;47 return GetStorableConversionAttribute(mi).SrcVersion; 42 48 } 43 49 } -
branches/PersistenceReintegration/HeuristicLab.Persistence/4.0/Core/StorableTypeAttribute.cs
r14925 r15034 37 37 38 38 public Guid Guid { get; private set; } 39 public uint Version { get; set; }39 public uint Version { get; private set; } 40 40 41 41 /// <summary> -
branches/PersistenceReintegration/HeuristicLab.Persistence/4.0/Core/TypeInfo.cs
r15020 r15034 59 59 if (StorableTypeAttribute != null) { 60 60 // check constructors ( 61 if (!type.IsValueType && !type.IsEnum && !type.IsInterface && 61 if (!type.IsValueType && !type.IsEnum && !type.IsInterface && 62 62 GetStorableConstructor() == null && GetDefaultConstructor() == null) 63 63 throw new PersistenceException("No storable constructor or parameterless constructor found."); 64 64 65 66 65 // traverse type hierarchy from base type to sub types 66 Stack<Type> types = new Stack<Type>(); 67 67 while (type != null) { 68 68 types.Push(type); … … 95 95 foreach (var property in propertyInfos) { 96 96 var attrib = StorableAttribute.GetStorableAttribute(property); 97 if ( !attrib.AllowOneWay && (!property.CanRead || !property.CanWrite))97 if ((!property.CanRead || !property.CanWrite) && (attrib == null || !attrib.AllowOneWay)) 98 98 throw new PersistenceException("Properties must be readable and writable or explicity enable one way serialization."); 99 99 -
branches/PersistenceReintegration/HeuristicLab.Persistence/4.0/Transformers/StorableClassTransformer.cs
r14927 r15034 72 72 var typeBox = mapper.GetBox(box.TypeId).GetExtension(TypeBox.Type); 73 73 var version = typeBox.HasVersion ? typeBox.Version : 1; 74 var typeGuid = typeInfo.StorableTypeAttribute.Guid; 74 75 75 76 var components = new Dictionary<uint, uint>(); … … 79 80 80 81 var conversionMethods = 81 type.GetMethods(BindingFlags.NonPublic | BindingFlags.Static) 82 type.Assembly.GetTypes().SelectMany(t => 83 t.GetMethods(BindingFlags.NonPublic | BindingFlags.Static) 82 84 .Where(StorableConversionAttribute.IsStorableConversionMethod) 83 .Where(mi => StorableConversionAttribute.GetVersion(mi) >= version) 84 .OrderBy(StorableConversionAttribute.GetVersion); 85 .Where(mi => StorableConversionAttribute.GetGuid(mi) == typeGuid && 86 StorableConversionAttribute.GetVersion(mi) >= version)) 87 .OrderBy(StorableConversionAttribute.GetVersion) 88 .ToArray(); 85 89 86 // put all objects into dictionary for optional conversion90 // put all objects into dictionary for conversion 87 91 var dict = new Dictionary<string, object>(); 88 92 foreach (var component in components) { … … 90 94 } 91 95 92 // TODO: check that all entries in the dictionary can be mapped to a field or property93 96 foreach (var convMeth in conversionMethods) { 97 if (StorableConversionAttribute.GetVersion(convMeth) != version) 98 throw new PersistenceException(string.Format("No conversion method defined for type {0} version {1}", typeGuid, version)); 94 99 dict = (Dictionary<string, object>)convMeth.Invoke(null, new object[] { dict }); 100 version++; 101 } 102 if (version != typeInfo.StorableTypeAttribute.Version) 103 throw new PersistenceException(string.Format("Missing one or more conversion methods for type {0} version {1}", 104 typeGuid, typeInfo.StorableTypeAttribute.Version)); 105 106 // set default values for all fields and properties 107 foreach (var componentInfo in typeInfo.Fields) { 108 var field = (FieldInfo)componentInfo.MemberInfo; 109 if (componentInfo.StorableAttribute != null && componentInfo.StorableAttribute.DefaultValue != null) 110 field.SetValue(obj, componentInfo.StorableAttribute.DefaultValue); 111 } 112 foreach (var componentInfo in typeInfo.Properties.Where(x => x.Writeable)) { 113 var property = (PropertyInfo)componentInfo.MemberInfo; 114 if (componentInfo.StorableAttribute != null && componentInfo.StorableAttribute.DefaultValue != null) 115 property.SetValue(obj, componentInfo.StorableAttribute.DefaultValue, null); 95 116 } 96 117 97 foreach (var componentInfo in typeInfo.Fields) { 98 var field = (FieldInfo)componentInfo.MemberInfo; 99 object val = null; 100 bool found = dict.TryGetValue(componentInfo.Name, out val); 101 if (found) 118 // set all members as generated by conversion method chain 119 foreach (var kvp in dict.ToArray()) { 120 var key = kvp.Key; 121 var val = kvp.Value; 122 var fieldInfo = typeInfo.Fields.FirstOrDefault(fi => fi.Name == key); 123 if (fieldInfo != null) { 124 var field = (FieldInfo)fieldInfo.MemberInfo; 102 125 field.SetValue(obj, val); 103 else if (componentInfo.StorableAttribute.DefaultValue != null) 104 field.SetValue(obj, componentInfo.StorableAttribute.DefaultValue); 126 dict.Remove(fieldInfo.Name); 127 continue; 128 } 129 var propInfo = typeInfo.Properties.Where(x => x.Writeable).FirstOrDefault(pi => pi.Name == key); 130 if (propInfo != null) { 131 var prop = (PropertyInfo)propInfo.MemberInfo; 132 prop.SetValue(obj, val, null); 133 dict.Remove(propInfo.Name); 134 continue; 135 } 105 136 } 106 137 107 foreach (var componentInfo in typeInfo.Properties.Where(x => x.Writeable)) { 108 var property = (PropertyInfo)componentInfo.MemberInfo; 109 object val = null; 110 bool found = dict.TryGetValue(componentInfo.Name, out val); 111 if (found) 112 property.SetValue(obj, val, null); 113 else if (componentInfo.StorableAttribute.DefaultValue != null) 114 property.SetValue(obj, componentInfo.StorableAttribute.DefaultValue, null); 115 } 138 if (dict.Any()) 139 throw new PersistenceException(string.Format("Invalid conversion method. The following members are undefined in type {0} version {1}: {2}", 140 typeGuid, typeInfo.StorableTypeAttribute.Version, 141 string.Join(", ", dict.Keys))); 116 142 117 143 var emptyArgs = new object[0]; -
branches/PersistenceReintegration/HeuristicLab.Persistence/4.0/Transformers/Transformers.cs
r15022 r15034 332 332 return ((Type)mapper.GetObject(b.GetGenericTypeIds(0))).MakeArrayType(); 333 333 } else { 334 334 335 return type; 335 336 } -
branches/PersistenceReintegration/HeuristicLab.Tests/HeuristicLab.Persistence-3.3/UseCasesPersistenceNew.cs
r15020 r15034 2166 2166 } 2167 2167 [StorableType("00000000-0000-0000-0000-BADCAFFEE000", 2)] // for testing (version 2) 2168 private partialclass V2 : NewBaseType {2168 private class V2 : NewBaseType { 2169 2169 [Storable] 2170 2170 public int a; … … 2186 2186 } 2187 2187 2188 // conversion part 2189 private partial class V2 : NewBaseType { 2190 [StorableConversion(srcVersion: 1)] 2188 [StorableType("00000000-0000-0000-0000-BADCAFFEE200", 3)] // for testing (version 3) 2189 private class V3 : NewBaseType { 2190 [Storable] 2191 public int a; 2192 2193 [Storable] 2194 public int[] val; 2195 2196 [Storable] 2197 public V3 mySelf; 2198 2199 [Storable] 2200 public Tuple<int, int> tup; 2201 2202 [Storable] 2203 public Point coords; 2204 } 2205 2206 private static class Conversions { 2207 [StorableConversion("D211A828-6440-4E72-A8C7-AA4F9B4FFA75", 1)] 2191 2208 private static Dictionary<string, object> ConvertV1(Dictionary<string, object> values) { 2192 2209 var newValues = new Dictionary<string, object>(); … … 2208 2225 return newValues; 2209 2226 } 2210 } 2211 2212 [StorableType("00000000-0000-0000-0000-BADCAFFEE200", 3)] // for testing (version 3) 2213 private partial class V3 : NewBaseType { 2214 [Storable] 2215 public int a; 2216 2217 [Storable] 2218 public int[] val; 2219 2220 [Storable] 2221 public V3 mySelf; 2222 2223 [Storable] 2224 public Tuple<int, int> tup; 2225 2226 [Storable] 2227 public Point coords; 2228 } 2229 2230 // conversion part 2231 private partial class V3 { 2232 [StorableConversion(srcVersion: 1)] 2233 private static Dictionary<string, object> ConvertV1(Dictionary<string, object> values) { 2234 var newValues = new Dictionary<string, object>(); 2235 var items = (ItemCollection<IItem>)values["OldBaseType.items"]; 2236 newValues["NewBaseType.items"] = items.Select(iv => new DoubleValue((double)(((dynamic)iv).Value))).ToArray(); 2237 newValues["V2.a"] = ((IntValue)values["V1.a"]).Value; 2238 newValues["V2.val"] = ((ItemList<IntValue>)values["V1.vals"]).Select(iv => iv.Value).ToArray(); 2239 2240 newValues["V2.mySelf"] = values["V1.mySelf"]; // myself type will be mapped correctly 2241 2242 var tup = (Tuple<int, int>)values["V1.tup"]; 2243 if (tup != null) { 2244 newValues["V2.TupItem1"] = tup.Item1; 2245 newValues["V2.TupItem2"] = tup.Item2; 2246 } 2247 2248 newValues["V2.coords"] = new Point((int)values["V1.x"], (int)values["V1.y"]); 2249 2250 return newValues; 2251 } 2252 2253 [StorableConversion(srcVersion: 2)] 2227 2228 [StorableConversion("D211A828-6440-4E72-A8C7-AA4F9B4FFA75", 2)] 2254 2229 private static Dictionary<string, object> ConvertV2(Dictionary<string, object> values) { 2255 2230 var newValues = new Dictionary<string, object>(); … … 2286 2261 Mapper.StaticCache.DeregisterType(StorableTypeAttribute.GetStorableTypeAttribute(typeof(V1)).Guid); 2287 2262 Mapper.StaticCache.DeregisterType(StorableTypeAttribute.GetStorableTypeAttribute(typeof(V2)).Guid); 2288 2289 Mapper.StaticCache.RegisterType(StorableTypeAttribute.GetStorableTypeAttribute(typeof(V1)).Guid, typeof(V2)); 2290 2291 object o = serializer.Deserialize(tempFile); 2292 var restored = (V2)o; 2263 Mapper.StaticCache.DeregisterType(StorableTypeAttribute.GetStorableTypeAttribute(typeof(V3)).Guid); 2264 2265 Mapper.StaticCache.RegisterType(StorableTypeAttribute.GetStorableTypeAttribute(typeof(V1)).Guid, typeof(V3)); 2266 var pi = typeof(StorableTypeAttribute).GetProperty("Guid"); 2267 pi.SetValue( 2268 Mapper.StaticCache.GetTypeInfo(typeof(V3)).StorableTypeAttribute, 2269 StorableTypeAttribute.GetStorableTypeAttribute(typeof(V1)).Guid, 2270 null); 2271 2272 object o = serializer.Deserialize(tempFile); 2273 var restored = (V3)o; 2293 2274 Assert.AreEqual(restored.a, old.a.Value); 2294 Assert.IsTrue(restored.val.SequenceEqual(old.vals.Select(iv => iv.Value))); 2295 Assert.IsTrue(restored.items.Select(item => item.Value).SequenceEqual(old.items.Select(iv => (double)((dynamic)iv).Value))); 2296 // Assert.AreSame(restored.items[0], restored.items[1]); 2297 Assert.AreSame(restored, restored.mySelf); 2298 2299 //string msg = Profile(test); 2300 //Console.WriteLine(msg); 2301 } 2302 2303 [TestMethod] 2304 [TestCategory("Persistence4")] 2305 [TestProperty("Time", "short")] 2306 public void TestConversion2() { 2307 var test = new Func<V2>(() => { 2308 var p = new V2(); 2309 p.a = 1; 2310 p.mySelf = p; 2311 p.val = new int[] { 2, 3, 4 }; 2312 p.TupItem1 = 17; 2313 p.TupItem2 = 4; 2314 p.items = new DoubleValue[] { new DoubleValue(1.0), new DoubleValue(2.0) }; 2315 return p; 2316 }); 2317 2318 ProtoBufSerializer serializer = new ProtoBufSerializer(); 2319 var old = test(); 2320 serializer.Serialize(old, tempFile); 2321 Mapper.StaticCache.DeregisterType(StorableTypeAttribute.GetStorableTypeAttribute(typeof(V1)).Guid); 2322 Mapper.StaticCache.DeregisterType(StorableTypeAttribute.GetStorableTypeAttribute(typeof(V2)).Guid); 2323 Mapper.StaticCache.DeregisterType(StorableTypeAttribute.GetStorableTypeAttribute(typeof(V3)).Guid); 2324 2325 Mapper.StaticCache.RegisterType(StorableTypeAttribute.GetStorableTypeAttribute(typeof(V2)).Guid, typeof(V3)); 2326 2327 object o = serializer.Deserialize(tempFile); 2328 var restored = (V3)o; 2329 Assert.AreEqual(restored.a, old.a); 2330 Assert.IsTrue(restored.val.SequenceEqual(old.val)); 2275 Assert.IsTrue(restored.val.SequenceEqual(old.vals.Select(iv=>iv.Value))); 2331 2276 Assert.IsTrue(restored.items.Select(item => item.Value).SequenceEqual(old.items.Select(iv => (double)((dynamic)iv).Value))); 2332 2277 // Assert.AreSame(restored.items[0], restored.items[1]);
Note: See TracChangeset
for help on using the changeset viewer.