Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Persistence/3.3/Auxiliary/TypeLoader.cs @ 11171

Last change on this file since 11171 was 11171, checked in by ascheibe, 10 years ago

#2115 merged r11170 (copyright update) into trunk

File size: 8.1 KB
RevLine 
[3743]1#region License Information
2/* HeuristicLab
[11171]3 * Copyright (C) 2002-2014 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
[3743]4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
[1454]22using System;
[8698]23using System.Collections.Generic;
[1682]24using System.Reflection;
[1823]25using HeuristicLab.Persistence.Core;
[4068]26using HeuristicLab.Tracing;
[1454]27
[1823]28namespace HeuristicLab.Persistence.Auxiliary {
[3004]29  internal class TypeLoader {
[8698]30    #region Mono Compatibility
[9014]31    private static TypeName cachedMonoRuntimeType;
32    private static TypeName cachedWindowsRuntimeType;
33    private static TypeName cachedMonoObjectEqualityComparerType;
34    private static TypeName cachedWindowsObjectEqualityComparerType;
[8698]35
[9014]36    private static bool MonoInstalled {
37      get { return Type.GetType("Mono.Runtime") != null; }
38    }
39
[8698]40    static TypeLoader() {
41      // we use Int32 here because we get all the information about Mono's mscorlib and just have to change the class name
[9014]42      cachedMonoRuntimeType = TypeNameParser.Parse(typeof(System.Int32).AssemblyQualifiedName);
43      cachedMonoRuntimeType = new TypeName(cachedMonoRuntimeType, "MonoType");
[8698]44
[9014]45      cachedWindowsRuntimeType = TypeNameParser.Parse(typeof(System.Int32).AssemblyQualifiedName);
46      cachedWindowsRuntimeType = new TypeName(cachedWindowsRuntimeType, "RuntimeType");
47
[8698]48      // we need the information about the Persistence assembly, so we use TypeName here because it is contained in this assembly
[9014]49      cachedMonoObjectEqualityComparerType = TypeNameParser.Parse(typeof(TypeName).AssemblyQualifiedName);
50      cachedMonoObjectEqualityComparerType = new TypeName(cachedMonoObjectEqualityComparerType, "ObjectEqualityComparer", "HeuristicLab.Persistence.Mono");
51
52      cachedWindowsObjectEqualityComparerType = TypeNameParser.Parse(typeof(System.Int32).AssemblyQualifiedName);
53      cachedWindowsObjectEqualityComparerType = new TypeName(cachedWindowsObjectEqualityComparerType, "ObjectEqualityComparer", "System.Collections.Generic");
[8698]54    }
55    #endregion
56
[8641]57    public static Type Load(string typeNameString) {
[8698]58      TypeName typeName = null;
[8641]59      try {
[8698]60        typeName = TypeNameParser.Parse(typeNameString);
61      }
62      catch (Exception) {
63        throw new PersistenceException(String.Format(
64           "Could not parse type string \"{0}\"",
65           typeNameString));
66      }
67
68      try {
[8641]69        // try to load type normally
[8698]70        return LoadInternal(typeName);
[8641]71      }
72      catch (PersistenceException) {
73        #region Mono Compatibility
[9014]74        // if that fails, try to convert to the corresponding Mono or .NET type
75        if (MonoInstalled) {
[9015]76          typeName = GetMonoType(typeName);
77          Logger.Info(String.Format(@"Trying to load Mono type ""{0}"" instead of .NET type ""{1}""",
78                                    typeName, typeNameString));
[9014]79        } else {
[9015]80          typeName = GetDotNetType(typeName);
81          Logger.Info(String.Format(@"Trying to load .NET type ""{0}"" instead of Mono type ""{1}""",
82                                    typeName, typeNameString));
83
[9014]84        }
[9015]85        return LoadInternal(typeName);
86        #endregion
[8641]87      }
88    }
[1780]89
[8698]90    private static Type LoadInternal(TypeName typeName) {
[1780]91      Type type;
92      try {
[8698]93        type = Type.GetType(typeName.ToString(true, true), true);
94      }
[4068]95      catch (Exception) {
[1780]96        Logger.Warn(String.Format(
[8698]97          "Cannot load type \"{0}\", falling back to partial name", typeName.ToString(true, true)));
98        type = LoadWithPartialName(typeName);
99        CheckCompatibility(typeName, type);
[8641]100      }
101      return type;
102    }
103
[8698]104    private static Type LoadWithPartialName(TypeName typeName) {
[8641]105      try {
[3036]106#pragma warning disable 0618
[8641]107        Assembly a = Assembly.LoadWithPartialName(typeName.AssemblyName);
108        // the suggested Assembly.Load() method fails to load assemblies outside the GAC
[3036]109#pragma warning restore 0618
[8641]110        return a.GetType(typeName.ToString(false, false), true);
111      }
112      catch (Exception) {
113        throw new PersistenceException(String.Format(
114          "Could not load type \"{0}\"",
[8698]115          typeName.ToString(true, true)));
[8641]116      }
117    }
118
[8698]119    private static void CheckCompatibility(TypeName typeName, Type type) {
[8641]120      try {
121        TypeName loadedTypeName = TypeNameParser.Parse(type.AssemblyQualifiedName);
[8698]122        if (!typeName.IsCompatible(loadedTypeName))
[1780]123          throw new PersistenceException(String.Format(
[8641]124            "Serialized type is incompatible with available type: serialized: {0}, loaded: {1}",
[8698]125            typeName.ToString(true, true),
[8641]126            type.AssemblyQualifiedName));
[8698]127        if (typeName.IsNewerThan(loadedTypeName))
[8641]128          throw new PersistenceException(String.Format(
129            "Serialized type is newer than available type: serialized: {0}, loaded: {1}",
[8698]130            typeName.ToString(true, true),
[8641]131            type.AssemblyQualifiedName));
[1780]132      }
[8641]133      catch (PersistenceException) {
134        throw;
135      }
136      catch (Exception e) {
137        Logger.Warn(String.Format(
138          "Could not perform version check requested type was {0} while loaded type is {1}:",
[8698]139          typeName.ToString(true, true),
[8641]140          type.AssemblyQualifiedName),
141                    e);
142      }
[1780]143    }
[8641]144
145    #region Mono Compatibility
146    /// <summary>
147    /// Returns the corresponding type for the Mono runtime
148    /// </summary>
149    /// <returns>
[8699]150    /// The remapped typeName, or the original typeName if no mapping was found
[8641]151    /// </returns>
[8698]152    private static TypeName GetMonoType(TypeName typeName) {
[8641]153      // map System.RuntimeType to System.MonoType
154      if (typeName.Namespace == "System" && typeName.ClassName == "RuntimeType") {
[9014]155        return cachedMonoRuntimeType;
[8698]156        // map System.Collections.Generic.ObjectEqualityComparer to HeuristicLab.Mono.ObjectEqualityComparer
[8641]157      } else if (typeName.Namespace == "System.Collections.Generic" && typeName.ClassName == "ObjectEqualityComparer") {
[9014]158        TypeName newTypeName = new TypeName(cachedMonoObjectEqualityComparerType);
[8698]159        newTypeName.GenericArgs = new List<TypeName>(typeName.GenericArgs);
160        return newTypeName;
[8641]161      }
[8698]162      return typeName;
[8641]163    }
[9014]164
165    /// <summary>
166    /// Returns the corresponding type for the .NET runtime
167    /// </summary>
168    /// <returns>
169    /// The remapped typeName, or the original typeName if no mapping was found
170    /// </returns>
171    private static TypeName GetDotNetType(TypeName typeName) {
172      // map System.MonoType to System.RuntimeType
173      if (typeName.Namespace == "System" && typeName.ClassName == "MonoType") {
174        return cachedWindowsRuntimeType;
[9015]175        // maps Mono's string comparer to System.Collections.Generic.ObjectEqualityComparer<string>
[9014]176      } else if (typeName.Namespace == "System.Collections.Generic" && typeName.ClassName == "InternalStringComparer") {
177        TypeName newTypeName = new TypeName(cachedWindowsObjectEqualityComparerType);
178        var genericArgsList = new List<TypeName>();
179        genericArgsList.Add(new TypeName(typeof(String).Namespace, "String"));
180        newTypeName.GenericArgs = genericArgsList;
181        return newTypeName;
182      } else if (typeName.Namespace == "System.Collections.Generic" && typeName.ClassName == "EqualityComparer+DefaultComparer") {
183        TypeName newTypeName = new TypeName(cachedWindowsObjectEqualityComparerType);
184        newTypeName.GenericArgs = new List<TypeName>(typeName.GenericArgs);
185        return newTypeName;
186      }
187      return typeName;
188    }
[8641]189    #endregion
[1780]190  }
[1454]191}
Note: See TracBrowser for help on using the repository browser.