Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
06/16/17 11:32:56 (7 years ago)
Author:
gkronber
Message:

#2520: improved conversions

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/PersistenceReintegration/HeuristicLab.Persistence/4.0/Transformers/StorableClassTransformer.cs

    r14927 r15034  
    7272      var typeBox = mapper.GetBox(box.TypeId).GetExtension(TypeBox.Type);
    7373      var version = typeBox.HasVersion ? typeBox.Version : 1;
     74      var typeGuid = typeInfo.StorableTypeAttribute.Guid;
    7475
    7576      var components = new Dictionary<uint, uint>();
     
    7980
    8081      var conversionMethods =
    81         type.GetMethods(BindingFlags.NonPublic | BindingFlags.Static)
     82        type.Assembly.GetTypes().SelectMany(t =>
     83          t.GetMethods(BindingFlags.NonPublic | BindingFlags.Static)
    8284          .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();
    8589
    86       // put all objects into dictionary for optional conversion
     90      // put all objects into dictionary for conversion
    8791      var dict = new Dictionary<string, object>();
    8892      foreach (var component in components) {
     
    9094      }
    9195
    92       // TODO: check that all entries in the dictionary can be mapped to a field or property
    9396      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));
    9499        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);
    95116      }
    96117
    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;
    102125          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        }
    105136      }
    106137
    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)));
    116142
    117143      var emptyArgs = new object[0];
Note: See TracChangeset for help on using the changeset viewer.