Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
05/11/09 16:09:29 (16 years ago)
Author:
epitzer
Message:

Store full version information with serialized data, only fall back to version invariant format if loading fails with full version. Also check, that loaded version is newer than requested version if possible. (#613)

Location:
trunk/sources/HeuristicLab.Persistence
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/sources/HeuristicLab.Persistence/3.3/Auxiliary/TypeStringBuilder.cs

    r1779 r1780  
    365365
    366366    public string ToString(bool full) {
     367      return ToString(full, true);
     368    }
     369
     370    public string ToString(bool full, bool includeAssembly) {
    367371      StringBuilder sb = new StringBuilder();
    368372      sb.Append(Namespace).Append('.').Append(ClassName);
     
    380384      }
    381385      sb.Append(MemoryMagic);
    382       if (AssemblyName != null)
     386      if (includeAssembly && AssemblyName != null) {
    383387        sb.Append(", ").Append(AssemblyName);
    384       if (full)
    385         foreach (var property in AssemblyAttribues)
    386           sb.Append(", ").Append(property.Key).Append('=').Append(property.Value);
     388        if (full)
     389          foreach (var property in AssemblyAttribues)
     390            sb.Append(", ").Append(property.Key).Append('=').Append(property.Value);
     391      }
    387392      return sb.ToString();
    388393    }
     
    393398
    394399    public bool IsOlderThan(TypeName t) {
    395       if (this.ClassName != t.ClassName ||
    396         this.Namespace != t.Namespace ||
    397         this.AssemblyName != t.AssemblyName)
    398         throw new Exception("Cannot compare versions of different types");
    399       if (CompareVersions(
    400         this.AssemblyAttribues["Version"],
    401         t.AssemblyAttribues["Version"]) < 0)
    402         return true;
    403       IEnumerator<TypeName> thisIt = this.GenericArgs.GetEnumerator();
    404       IEnumerator<TypeName> tIt = t.GenericArgs.GetEnumerator();
    405       while (thisIt.MoveNext()) {
    406         tIt.MoveNext();
    407         if (thisIt.Current.IsOlderThan(tIt.Current))
     400      try {
     401        if (this.ClassName != t.ClassName ||
     402          this.Namespace != t.Namespace ||
     403          this.AssemblyName != t.AssemblyName)
     404          throw new Exception("Cannot compare versions of different types");
     405        if (CompareVersions(
     406          this.AssemblyAttribues["Version"],
     407          t.AssemblyAttribues["Version"]) < 0)
    408408          return true;
    409       }
    410       return false;
     409        IEnumerator<TypeName> thisIt = this.GenericArgs.GetEnumerator();
     410        IEnumerator<TypeName> tIt = t.GenericArgs.GetEnumerator();
     411        while (thisIt.MoveNext()) {
     412          tIt.MoveNext();
     413          if (thisIt.Current.IsOlderThan(tIt.Current))
     414            return true;
     415        }
     416        return false;
     417      } catch (KeyNotFoundException) {
     418        throw new Exception("Could not extract version information from type string");
     419      }
    411420    }
    412421
  • trunk/sources/HeuristicLab.Persistence/3.3/Core/DeSerializer.cs

    r1779 r1780  
    99namespace HeuristicLab.Persistence.Core {
    1010
     11  public class TypeLoader {
     12
     13    public static Type Load(string typeNameString) {
     14      Type type;
     15      try {
     16        type = Type.GetType(typeNameString, true);
     17      } catch (Exception) {
     18        Logger.Warn(String.Format(
     19          "Cannot load type \"{0}\", falling back to loading with partial name", typeNameString));
     20        try {
     21          TypeName typeName = TypeNameParser.Parse(typeNameString);
     22          Assembly a = Assembly.LoadWithPartialName(typeName.AssemblyName);
     23          type = a.GetType(typeName.ToString(false, false), true);
     24        } catch (Exception) {
     25          throw new PersistenceException(String.Format(
     26            "Could not load type \"{0}\"",
     27            typeNameString));
     28        }
     29        try {
     30          if (
     31            TypeNameParser.Parse(type.AssemblyQualifiedName).IsOlderThan(
     32            TypeNameParser.Parse(typeNameString)))
     33            throw new PersistenceException(String.Format(
     34              "Serialized type is newer than available type: serialized: {0}, loaded: {1}",
     35              typeNameString,
     36              type.AssemblyQualifiedName));
     37        } catch (PersistenceException) {
     38          throw;
     39        } catch (Exception e) {
     40          Logger.Warn(String.Format(
     41            "Could not perform version check requested type was {0} while loaded type is {1}:",
     42            typeNameString,
     43            type.AssemblyQualifiedName),
     44            e);
     45        }
     46      }
     47      return type;
     48    }
     49
     50  }
     51
    1152  public class Deserializer {
    1253
     
    71112        var map = new Dictionary<Type, object>();
    72113        foreach (var typeMapping in typeCache) {
    73           Type type;
    74           try {
    75             type = Type.GetType(typeMapping.TypeName, true);
    76           } catch (Exception) {
    77             Logger.Error(String.Format(
    78               "Cannot load type \"{0}\", falling back to loading with partial name", typeMapping.TypeName));
    79             string[] typeNameParts = typeMapping.TypeName.Split(new[] { ',' });
    80             try {
    81               Assembly a = Assembly.LoadWithPartialName(typeNameParts[typeNameParts.Length - 1].Trim());
    82               Array.Resize(ref typeNameParts, typeNameParts.Length - 1);
    83               type = a.GetType(string.Join(",", typeNameParts), true);
    84             } catch (Exception) {
    85               throw new PersistenceException(String.Format(
    86                 "Could not load type \"{0}\"",
    87                 typeMapping.TypeName));
    88             }
    89           }
     114          Type type = TypeLoader.Load(typeMapping.TypeName);
    90115          typeIds.Add(typeMapping.Id, type);
    91           Type serializerType = Type.GetType(typeMapping.Serializer, true);
     116          Type serializerType = TypeLoader.Load(typeMapping.Serializer);
    92117          map.Add(type, Activator.CreateInstance(serializerType, true));
    93118        }
     
    101126      }
    102127    }
     128
    103129
    104130    public object Deserialize(IEnumerable<ISerializationToken> tokens) {
  • trunk/sources/HeuristicLab.Persistence/3.3/Core/Serializer.cs

    r1710 r1780  
    4040          IFormatter f = configuration.GetFormatter(pair.Key);
    4141          if (f != null) {
    42             serializer = f.GetType().VersionInvariantName();
     42            serializer = f.GetType().AssemblyQualifiedName;
    4343          } else {
    4444            IDecomposer d = configuration.GetDecomposer(pair.Key);
    45             serializer = d.GetType().VersionInvariantName();
     45            serializer = d.GetType().AssemblyQualifiedName;
    4646          }
     47          //result.Add(new TypeMapping(pair.Value, pair.Key.AssemblyQualifiedName, serializer));
    4748          result.Add(new TypeMapping(pair.Value, pair.Key.VersionInvariantName(), serializer));
    4849        }
  • trunk/sources/HeuristicLab.Persistence/UnitTests/UseCases.cs

    r1779 r1780  
    1515using HeuristicLab.Persistence.Default.Decomposers;
    1616using HeuristicLab.Persistence.Auxiliary;
     17using System.Text.RegularExpressions;
    1718
    1819namespace HeuristicLab.Persistence.UnitTest {
     
    510511
    511512    [TestMethod]
    512     public void TestSavingException() {     
     513    public void TestSavingException() {
    513514      List<int> list = new List<int> { 1, 2, 3 };
    514515      XmlGenerator.Serialize(list, tempFile);
     
    528529      string shortName =
    529530        "System.Collections.Generic.List`1[[System.Int32, mscorlib]][], mscorlib";
    530       Assert.AreEqual(name, TypeNameParser.Parse(name).ToString());       
     531      Assert.AreEqual(name, TypeNameParser.Parse(name).ToString());
    531532      Assert.AreEqual(shortName, TypeNameParser.Parse(name).ToString(false));
    532533      Assert.AreEqual(shortName, typeof(List<int>[]).VersionInvariantName());
     534    }
     535
     536    [TestMethod]
     537    public void TestAssemblyVersionCheck() {
     538      IntWrapper i = new IntWrapper(1);
     539      Serializer s = new Serializer(i, ConfigurationService.Instance.GetDefaultConfig(new XmlFormat()));
     540      XmlGenerator g = new XmlGenerator();
     541      StringBuilder dataString = new StringBuilder();
     542      foreach (var token in s) {
     543        dataString.Append(g.Format(token));
     544      }
     545      StringBuilder typeString = new StringBuilder();
     546      foreach (var line in g.Format(s.TypeCache))
     547        typeString.Append(line);
     548      Deserializer d = new Deserializer(XmlParser.ParseTypeCache(new StringReader(typeString.ToString())));
     549      XmlParser p = new XmlParser(new StringReader(dataString.ToString()));
     550      IntWrapper newI = (IntWrapper)d.Deserialize(p);
     551      Assert.AreEqual(i.Value, newI.Value);
     552      string newTypeString = Regex.Replace(typeString.ToString(),
     553        "Version=(\\d+\\.\\d+\\.\\d+\\.\\d+)",
     554        "Version=9999.9999.9999.9999");
     555      try {
     556        d = new Deserializer(XmlParser.ParseTypeCache(new StringReader(newTypeString)));
     557        Assert.Fail("Exception expected");
     558      } catch (PersistenceException) {
     559        // EXPECTED
     560      }
    533561    }
    534562
     
    536564    public static void Initialize(TestContext testContext) {
    537565      ConfigurationService.Instance.Reset();
    538     }   
    539   } 
     566    }
     567  }
    540568}
Note: See TracChangeset for help on using the changeset viewer.