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

Location:
branches/PersistenceReintegration/HeuristicLab.Persistence/4.0
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • branches/PersistenceReintegration/HeuristicLab.Persistence/4.0/Core/StorableConversionAttribute.cs

    r14927 r15034  
    2626  [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
    2727  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; }
    2930
    30     public StorableConversionAttribute(uint srcVersion) {
     31    public StorableConversionAttribute(string guid, uint srcVersion) {
     32      this.Guid = new Guid(guid);
    3133      this.SrcVersion = srcVersion;
    3234    }
     
    3537      return Attribute.IsDefined(mi, typeof(StorableConversionAttribute), false);
    3638    }
    37     public static StorableConversionAttribute GetTransformerAttribute(MethodInfo mi) {
     39
     40    public static StorableConversionAttribute GetStorableConversionAttribute(MethodInfo mi) {
    3841      return (StorableConversionAttribute)Attribute.GetCustomAttribute(mi, typeof(StorableConversionAttribute), false);
    3942    }
     43    public static Guid GetGuid(MethodInfo mi) {
     44      return GetStorableConversionAttribute(mi).Guid;
     45    }
    4046    public static uint GetVersion(MethodInfo mi) {
    41       return GetTransformerAttribute(mi).SrcVersion;
     47      return GetStorableConversionAttribute(mi).SrcVersion;
    4248    }
    4349  }
  • branches/PersistenceReintegration/HeuristicLab.Persistence/4.0/Core/StorableTypeAttribute.cs

    r14925 r15034  
    3737
    3838    public Guid Guid { get; private set; }
    39     public uint Version { get; set; }
     39    public uint Version { get; private set; }
    4040
    4141    /// <summary>
  • branches/PersistenceReintegration/HeuristicLab.Persistence/4.0/Core/TypeInfo.cs

    r15020 r15034  
    5959      if (StorableTypeAttribute != null) {
    6060        // check constructors (
    61         if (!type.IsValueType && !type.IsEnum && !type.IsInterface && 
     61        if (!type.IsValueType && !type.IsEnum && !type.IsInterface &&
    6262          GetStorableConstructor() == null && GetDefaultConstructor() == null)
    6363          throw new PersistenceException("No storable constructor or parameterless constructor found.");
    6464
    65           // traverse type hierarchy from base type to sub types
    66           Stack<Type> types = new Stack<Type>();
     65        // traverse type hierarchy from base type to sub types
     66        Stack<Type> types = new Stack<Type>();
    6767        while (type != null) {
    6868          types.Push(type);
     
    9595            foreach (var property in propertyInfos) {
    9696              var attrib = StorableAttribute.GetStorableAttribute(property);
    97               if (!attrib.AllowOneWay && (!property.CanRead || !property.CanWrite))
     97              if ((!property.CanRead || !property.CanWrite) && (attrib == null || !attrib.AllowOneWay))
    9898                throw new PersistenceException("Properties must be readable and writable or explicity enable one way serialization.");
    9999
  • 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];
  • branches/PersistenceReintegration/HeuristicLab.Persistence/4.0/Transformers/Transformers.cs

    r15022 r15034  
    332332        return ((Type)mapper.GetObject(b.GetGenericTypeIds(0))).MakeArrayType();
    333333      } else {
     334       
    334335        return type;
    335336      }
Note: See TracChangeset for help on using the changeset viewer.