static TypeLoader() { // we use Int32 here because we get all the information about Mono's mscorlib and just have to change the class name cachedMonoRuntimeType = TypeNameParser.Parse(typeof(System.Int32).AssemblyQualifiedName); cachedMonoRuntimeType = new TypeName(cachedMonoRuntimeType, "MonoType"); cachedWindowsRuntimeType = TypeNameParser.Parse(typeof(System.Int32).AssemblyQualifiedName); cachedWindowsRuntimeType = new TypeName(cachedWindowsRuntimeType, "RuntimeType"); // we need the information about the Persistence assembly, so we use TypeName here because it is contained in this assembly cachedMonoObjectEqualityComparerType = TypeNameParser.Parse(typeof(TypeName).AssemblyQualifiedName); cachedMonoObjectEqualityComparerType = new TypeName(cachedMonoObjectEqualityComparerType, "ObjectEqualityComparer", "HeuristicLab.Persistence.Mono"); cachedWindowsObjectEqualityComparerType = TypeNameParser.Parse(typeof(System.Int32).AssemblyQualifiedName); cachedWindowsObjectEqualityComparerType = new TypeName(cachedWindowsObjectEqualityComparerType, "ObjectEqualityComparer", "System.Collections.Generic"); }
private TypeName TransformSimpleTypeSpec() { var nameSpace = new List<string> { ConsumeIdentifier() }; while (ConsumeToken(Token.Symbol.Dot)) nameSpace.Add(ConsumeIdentifier()); var className = new List<string>(); if (nameSpace.Count > 0) { className.Add(nameSpace[nameSpace.Count - 1]); nameSpace.RemoveAt(nameSpace.Count - 1); } var genericArgCounts = new List<int> { ConsumeToken(Token.Symbol.Backtick) ? ConsumeNumber() : 0 }; while (ConsumeToken(Token.Symbol.Plus)) { className.Add(ConsumeIdentifier()); genericArgCounts.Add(ConsumeToken(Token.Symbol.Backtick) ? ConsumeNumber() : 0); } var nGenericArgs = genericArgCounts.Sum(); var typeName = new TypeName( string.Join(".", nameSpace.ToArray()), string.Join("+", className.ToArray()), nGenericArgs > genericArgCounts.Last() ? genericArgCounts : null); if (nGenericArgs > 0 && ConsumeToken(Token.Symbol.OpenBracket, true)) { typeName.GenericArgs.AddRange(TransformGenerics()); ConsumeToken(Token.Symbol.CloseBracket, true); } var pointerOrArray = new StringBuilder(); while (true) { if (ConsumeToken(Token.Symbol.Asterisk)) { pointerOrArray.Append("*"); } else if (ConsumeToken(Token.Symbol.OpenBracket)) { pointerOrArray.Append('['); ParseDimension(pointerOrArray); while (ConsumeToken(Token.Symbol.Comma)) { pointerOrArray.Append(","); ParseDimension(pointerOrArray); } ConsumeToken(Token.Symbol.CloseBracket, true); pointerOrArray.Append(']'); } else { break; } } typeName.MemoryMagic = pointerOrArray.ToString(); if (ConsumeComma()) { var sb = new StringBuilder(); sb.Append(ConsumeIdentifier()); while (CanConsumeToken(Token.Symbol.Dot) || CanConsumeToken(Token.Symbol.Dash) || CanConsumeNumber() || CanConsumeIdentifier()) { if (ConsumeToken(Token.Symbol.Dot)) sb.Append('.'); else if (ConsumeToken(Token.Symbol.Dash)) sb.Append('-'); else if (CanConsumeNumber()) sb.Append(ConsumeNumber()); else sb.Append(ConsumeIdentifier()); } typeName.AssemblyName = sb.ToString(); while (ConsumeComma()) { KeyValuePair<string, string> property = TransformAssemblyProperty(); typeName.AssemblyAttribues.Add(property.Key, property.Value); } } return typeName; }
/// <summary> /// Make sure major and minor version number are identical. This function /// recursively checks generic type arguments. /// </summary> /// <param name="typeName">Name of the type.</param> /// <returns> /// <c>true</c> if the specified type names are compatible; otherwise, <c>false</c>. /// </returns> public bool IsCompatible(TypeName typeName) { try { if (this.ClassName != typeName.ClassName || this.Namespace != typeName.Namespace || this.AssemblyName != typeName.AssemblyName) throw new Exception("Cannot compare versions of different types"); Version thisVersion = new Version(this.AssemblyAttribues["Version"]); Version tVersion = new Version(typeName.AssemblyAttribues["Version"]); if (this.AssemblyName == "mscorlib" && (thisVersion.Major == 2 || thisVersion.Major == 4) && (tVersion.Major == 2 || tVersion.Major == 4)) { // skip version check } else if (thisVersion.Major != tVersion.Major || thisVersion.Minor != tVersion.Minor) return false; IEnumerator<TypeName> thisIt = this.GenericArgs.GetEnumerator(); IEnumerator<TypeName> tIt = typeName.GenericArgs.GetEnumerator(); while (thisIt.MoveNext()) { tIt.MoveNext(); if (!thisIt.Current.IsCompatible(tIt.Current)) return false; } return true; } catch (KeyNotFoundException) { throw new Exception("Could not extract version infomration from type string"); } }
/// <summary> /// Lexicographically compare version information and make sure type and assembly /// names are identical. This function recursively checks generic type arguments. /// </summary> /// <param name="typeName">Name of the type.</param> /// <returns> /// <c>true</c> if is newer than the specified type name; otherwise, <c>false</c>. /// </returns> public bool IsNewerThan(TypeName typeName) { try { if (this.ClassName != typeName.ClassName || this.Namespace != typeName.Namespace || this.AssemblyName != typeName.AssemblyName) throw new Exception("Cannot compare versions of different types"); if (CompareVersions( this.AssemblyAttribues["Version"], typeName.AssemblyAttribues["Version"]) > 0) return true; IEnumerator<TypeName> thisIt = this.GenericArgs.GetEnumerator(); IEnumerator<TypeName> tIt = typeName.GenericArgs.GetEnumerator(); while (thisIt.MoveNext()) { tIt.MoveNext(); if (thisIt.Current.IsNewerThan(tIt.Current)) return true; } return false; } catch (KeyNotFoundException) { throw new Exception("Could not extract version information from type string"); } }
internal TypeName(TypeName typeName, string className = null, string nameSpace = null) { Namespace = nameSpace ?? typeName.Namespace; ClassName = className ?? typeName.ClassName; GenericArgs = new List<TypeName>(typeName.GenericArgs); AssemblyAttribues = new Dictionary<string, string>(typeName.AssemblyAttribues); MemoryMagic = typeName.MemoryMagic; AssemblyName = typeName.AssemblyName; IsReference = typeName.IsReference; if (typeName.GenericArgCounts != null) GenericArgCounts = typeName.GenericArgCounts.ToList(); }
private static Type LoadInternal(TypeName typeName) { Type type; try { type = Type.GetType(typeName.ToString(true, true), true); } catch (Exception) { Logger.Warn(String.Format( "Cannot load type \"{0}\", falling back to partial name", typeName.ToString(true, true))); type = LoadWithPartialName(typeName); CheckCompatibility(typeName, type); } return type; }
/// <summary> /// Returns the corresponding type for the .NET runtime /// </summary> /// <returns> /// The remapped typeName, or the original typeName if no mapping was found /// </returns> private static TypeName GetDotNetType(TypeName typeName) { // map System.MonoType to System.RuntimeType if (typeName.Namespace == "System" && typeName.ClassName == "MonoType") { return cachedWindowsRuntimeType; // maps Mono's string comparer to System.Collections.Generic.ObjectEqualityComparer<string> } else if (typeName.Namespace == "System.Collections.Generic" && typeName.ClassName == "InternalStringComparer") { TypeName newTypeName = new TypeName(cachedWindowsObjectEqualityComparerType); var genericArgsList = new List<TypeName>(); genericArgsList.Add(new TypeName(typeof(String).Namespace, "String")); newTypeName.GenericArgs = genericArgsList; return newTypeName; } else if (typeName.Namespace == "System.Collections.Generic" && typeName.ClassName == "EqualityComparer+DefaultComparer") { TypeName newTypeName = new TypeName(cachedWindowsObjectEqualityComparerType); newTypeName.GenericArgs = new List<TypeName>(typeName.GenericArgs); return newTypeName; } return typeName; }
/// <summary> /// Returns the corresponding type for the Mono runtime /// </summary> /// <returns> /// The remapped typeName, or the original typeName if no mapping was found /// </returns> private static TypeName GetMonoType(TypeName typeName) { // map System.RuntimeType to System.MonoType if (typeName.Namespace == "System" && typeName.ClassName == "RuntimeType") { return cachedMonoRuntimeType; // map System.Collections.Generic.ObjectEqualityComparer to HeuristicLab.Mono.ObjectEqualityComparer } else if (typeName.Namespace == "System.Collections.Generic" && typeName.ClassName == "ObjectEqualityComparer") { TypeName newTypeName = new TypeName(cachedMonoObjectEqualityComparerType); newTypeName.GenericArgs = new List<TypeName>(typeName.GenericArgs); return newTypeName; } return typeName; }
private static void CheckCompatibility(TypeName typeName, Type type) { try { TypeName loadedTypeName = TypeNameParser.Parse(type.AssemblyQualifiedName); if (!typeName.IsCompatible(loadedTypeName)) throw new PersistenceException(String.Format( "Serialized type is incompatible with available type: serialized: {0}, loaded: {1}", typeName.ToString(true, true), type.AssemblyQualifiedName)); if (typeName.IsNewerThan(loadedTypeName)) throw new PersistenceException(String.Format( "Serialized type is newer than available type: serialized: {0}, loaded: {1}", typeName.ToString(true, true), type.AssemblyQualifiedName)); } catch (PersistenceException) { throw; } catch (Exception e) { Logger.Warn(String.Format( "Could not perform version check requested type was {0} while loaded type is {1}:", typeName.ToString(true, true), type.AssemblyQualifiedName), e); } }
private static Type LoadWithPartialName(TypeName typeName) { try { #pragma warning disable 0618 Assembly a = Assembly.LoadWithPartialName(typeName.AssemblyName); // the suggested Assembly.Load() method fails to load assemblies outside the GAC #pragma warning restore 0618 return a.GetType(typeName.ToString(false, false), true); } catch (Exception) { throw new PersistenceException(String.Format( "Could not load type \"{0}\"", typeName.ToString(true, true))); } }