Changeset 8641


Ignore:
Timestamp:
09/13/12 11:49:29 (7 years ago)
Author:
ascheibe
Message:

#1952 (#1937) added Mono support to persistence

Location:
trunk/sources/HeuristicLab.Persistence/3.3
Files:
1 added
4 edited

Legend:

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

    r7259 r8641  
    2626
    2727namespace HeuristicLab.Persistence.Auxiliary {
     28  internal class TypeLoader {
     29    public static Type Load(string typeNameString) {
     30      try {
     31        // try to load type normally
     32        return LoadInternal(typeNameString);
     33      }
     34      catch (PersistenceException) {
     35        #region Mono Compatibility
     36        // if that fails, try to load Mono type
     37        string monoTypeNameString = GetMonoType(typeNameString);
     38        Logger.Info(String.Format(@"Trying to load Mono type ""{0}"" instead of type ""{1}""",
     39                                  monoTypeNameString, typeNameString));
     40        return LoadInternal(monoTypeNameString);
     41      }
     42        #endregion
     43    }
    2844
    29   internal class TypeLoader {
    30 
    31     public static Type Load(string typeNameString) {
     45    private static Type LoadInternal(string typeNameString) {
    3246      Type type;
    3347      try {
    3448        type = Type.GetType(typeNameString, true);
     49        #region Mono Compatibility
     50        // mono: workaround until Mono bug #580 (http://bugzilla.xamarin.com/show_bug.cgi?id=580) is fixed
     51        if (type.AssemblyQualifiedName != typeNameString)
     52          throw new TypeLoadException(
     53            String.Format(
     54            @"Could not load requested type ""{0}"", loaded ""{1}"" instead.",
     55            typeNameString, type.AssemblyQualifiedName));
     56        #endregion
    3557      }
    3658      catch (Exception) {
    3759        Logger.Warn(String.Format(
    3860          "Cannot load type \"{0}\", falling back to partial name", typeNameString));
    39         try {
    40           TypeName typeName = TypeNameParser.Parse(typeNameString);
    41 #pragma warning disable 0618
    42           Assembly a = Assembly.LoadWithPartialName(typeName.AssemblyName);
    43           // the suggested Assembly.Load() method fails to load assemblies outside the GAC
    44 #pragma warning restore 0618
    45           type = a.GetType(typeName.ToString(false, false), true);
    46         }
    47         catch (Exception) {
    48           throw new PersistenceException(String.Format(
    49             "Could not load type \"{0}\"",
    50             typeNameString));
    51         }
    52         try {
    53           TypeName requestedTypeName = TypeNameParser.Parse(typeNameString);
    54           TypeName loadedTypeName = TypeNameParser.Parse(type.AssemblyQualifiedName);
    55           if (!requestedTypeName.IsCompatible(loadedTypeName))
    56             throw new PersistenceException(String.Format(
    57               "Serialized type is incompatible with available type: serialized: {0}, loaded: {1}",
    58               typeNameString,
    59               type.AssemblyQualifiedName));
    60           if (requestedTypeName.IsNewerThan(loadedTypeName))
    61             throw new PersistenceException(String.Format(
    62               "Serialized type is newer than available type: serialized: {0}, loaded: {1}",
    63               typeNameString,
    64               type.AssemblyQualifiedName));
    65         }
    66         catch (PersistenceException) {
    67           throw;
    68         }
    69         catch (Exception e) {
    70           Logger.Warn(String.Format(
    71             "Could not perform version check requested type was {0} while loaded type is {1}:",
    72             typeNameString,
    73             type.AssemblyQualifiedName),
    74             e);
    75         }
     61        type = LoadWithPartialName(typeNameString);
     62        CheckCompatibility(typeNameString, type);
    7663      }
    7764      return type;
    7865    }
     66
     67    private static Type LoadWithPartialName(string typeNameString) {
     68      try {
     69        TypeName typeName = TypeNameParser.Parse(typeNameString);
     70#pragma warning disable 0618
     71        Assembly a = Assembly.LoadWithPartialName(typeName.AssemblyName);
     72        // the suggested Assembly.Load() method fails to load assemblies outside the GAC
     73#pragma warning restore 0618
     74        return a.GetType(typeName.ToString(false, false), true);
     75      }
     76      catch (Exception) {
     77        throw new PersistenceException(String.Format(
     78          "Could not load type \"{0}\"",
     79          typeNameString));
     80      }
     81    }
     82
     83    private static void CheckCompatibility(string typeNameString, Type type) {
     84      try {
     85        TypeName requestedTypeName = TypeNameParser.Parse(typeNameString);
     86        TypeName loadedTypeName = TypeNameParser.Parse(type.AssemblyQualifiedName);
     87        if (!requestedTypeName.IsCompatible(loadedTypeName))
     88          throw new PersistenceException(String.Format(
     89            "Serialized type is incompatible with available type: serialized: {0}, loaded: {1}",
     90            typeNameString,
     91            type.AssemblyQualifiedName));
     92        if (requestedTypeName.IsNewerThan(loadedTypeName))
     93          throw new PersistenceException(String.Format(
     94            "Serialized type is newer than available type: serialized: {0}, loaded: {1}",
     95            typeNameString,
     96            type.AssemblyQualifiedName));
     97      }
     98      catch (PersistenceException) {
     99        throw;
     100      }
     101      catch (Exception e) {
     102        Logger.Warn(String.Format(
     103          "Could not perform version check requested type was {0} while loaded type is {1}:",
     104          typeNameString,
     105          type.AssemblyQualifiedName),
     106                    e);
     107      }
     108    }
     109
     110    #region Mono Compatibility
     111    /// <summary>
     112    /// Returns the corresponding type for the Mono runtime
     113    /// </summary>
     114    /// <returns>
     115    /// The remapped typeNameString, or the original string if no mapping was found
     116    /// </returns>
     117    private static string GetMonoType(string typeNameString) {
     118      TypeName typeName = TypeNameParser.Parse(typeNameString);
     119
     120      // map System.RuntimeType to System.MonoType
     121      if (typeName.Namespace == "System" && typeName.ClassName == "RuntimeType") {
     122        // we use Int32 here because we get all the information about Mono's mscorlib and just have to change the class name
     123        typeName = TypeNameParser.Parse(typeof(System.Int32).AssemblyQualifiedName);
     124        typeName.ClassName = "MonoType";
     125      } else if (typeName.Namespace == "System.Collections.Generic" && typeName.ClassName == "ObjectEqualityComparer") {
     126        // map System.Collections.Generic.ObjectEqualityComparer to HeuristicLab.Mono.ObjectEqualityComparer       
     127        // we need the information about the Persistence assembly, so we use TypeName here because it is contained in this assembly
     128        TypeName oecInfo = TypeNameParser.Parse(typeof(TypeName).AssemblyQualifiedName);
     129        typeName.Namespace = "HeuristicLab.Persistence.Mono";
     130        typeName.AssemblyName = oecInfo.AssemblyName;
     131        typeName.AssemblyAttribues.Clear();
     132        typeName.AssemblyAttribues["Version"] = oecInfo.AssemblyAttribues["Version"];
     133        typeName.AssemblyAttribues["Culture"] = oecInfo.AssemblyAttribues["Culture"];
     134        typeName.AssemblyAttribues["PublicKeyToken"] = oecInfo.AssemblyAttribues["PublicKeyToken"];
     135      }
     136
     137      return typeName.ToString(true, true);
     138    }
     139    #endregion
    79140  }
    80141}
  • trunk/sources/HeuristicLab.Persistence/3.3/Auxiliary/TypeName.cs

    r7259 r8641  
    4141    /// <value>The namespace.</value>
    4242    [Storable]
    43     public string Namespace { get; private set; }
     43    #region Mono Compatibility
     44    // mono: setting the namespace is needed for generating ObjectEqualityComparer type names in the TypeLoader
     45    public string Namespace { get; internal set; }
     46    #endregion
    4447
    4548    /// <summary>
     
    4851    /// <value>The name of the class.</value>
    4952    [Storable]
    50     public string ClassName { get; private set; }
     53    #region Mono Compatibility
     54    public string ClassName { get; internal set; }
     55    #endregion
    5156
    5257    /// <summary>
     
    235240        }
    236241        return false;
    237       } catch (KeyNotFoundException) {
     242      }
     243      catch (KeyNotFoundException) {
    238244        throw new Exception("Could not extract version information from type string");
    239245      }
     
    272278        }
    273279        return true;
    274       } catch (KeyNotFoundException) {
     280      }
     281      catch (KeyNotFoundException) {
    275282        throw new Exception("Could not extract version infomration from type string");
    276283      }
  • trunk/sources/HeuristicLab.Persistence/3.3/Default/CompositeSerializers/TypeSerializer.cs

    r7259 r8641  
    4141
    4242    public bool CanSerialize(Type type) {
     43      #region Mono Compatibility
    4344      return type == typeof(Type) ||
    44              type.VersionInvariantName() == "System.RuntimeType, mscorlib";
     45        type.VersionInvariantName() == "System.RuntimeType, mscorlib" ||
     46        type.VersionInvariantName() == "System.MonoType, mscorlib";
     47      #endregion
    4548    }
    4649
    4750    public string JustifyRejection(Type type) {
    48       return "not System.Type nor System.RuntimeType";
     51      #region Mono Compatibility
     52      return "not System.Type, System.RuntimeType, System.MonoType";
     53      #endregion
    4954    }
    5055
  • trunk/sources/HeuristicLab.Persistence/3.3/HeuristicLab.Persistence-3.3.csproj

    r8600 r8641  
    125125  </ItemGroup>
    126126  <ItemGroup>
     127    <Compile Include="Auxiliary\ObjectEqualityComparer.cs" />
    127128    <Compile Include="Auxiliary\StringExtensions.cs" />
    128129    <Compile Include="Auxiliary\TypeLoader.cs" />
     
    246247  </ItemGroup>
    247248  <PropertyGroup>
    248    <PreBuildEvent Condition=" '$(OS)' == 'Windows_NT' ">set Path=%25Path%25;$(ProjectDir);$(SolutionDir)
     249    <PreBuildEvent Condition=" '$(OS)' == 'Windows_NT' ">set Path=%25Path%25;$(ProjectDir);$(SolutionDir)
    249250set ProjectDir=$(ProjectDir)
    250251set SolutionDir=$(SolutionDir)
     
    253254call PreBuildEvent.cmd
    254255</PreBuildEvent>
    255 <PreBuildEvent Condition=" '$(OS)' != 'Windows_NT' ">
     256    <PreBuildEvent Condition=" '$(OS)' != 'Windows_NT' ">
    256257export ProjectDir=$(ProjectDir)
    257258export SolutionDir=$(SolutionDir)
Note: See TracChangeset for help on using the changeset viewer.