#region License Information /* HeuristicLab * Copyright (C) 2002-2010 Heuristic and Evolutionary Algorithms Laboratory (HEAL) * * This file is part of HeuristicLab. * * HeuristicLab is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * HeuristicLab is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with HeuristicLab. If not, see . */ #endregion using System; using System.Collections.Generic; using System.Linq; using System.Text; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; namespace HeuristicLab.Persistence.Auxiliary { /// /// Contains a more modular representation of type names that can /// be used to compare versions and ignore extended assembly /// attributes. /// [StorableClass] public class TypeName { /// /// Gets or sets the namespace. /// /// The namespace. [Storable] public string Namespace { get; private set; } /// /// Gets or sets the name of the class. /// /// The name of the class. [Storable] public string ClassName { get; private set; } /// /// Gets or sets the generic args. /// /// The generic args. [Storable] public List GenericArgs { get; internal set; } /// /// Gets a value indicating whether this instance is generic. /// /// /// true if this instance is generic; otherwise, false. /// public bool IsGeneric { get { return GenericArgs.Count > 0; } } /// /// Gets or sets the memory magic (point or array declaration). /// /// The memory magic. [Storable] public string MemoryMagic { get; internal set; } /// /// Gets or sets the name of the assembly. /// /// The name of the assembly. [Storable] public string AssemblyName { get; internal set; } /// /// Gets or sets the assembly attribues. /// /// The assembly attribues. [Storable] public Dictionary AssemblyAttribues { get; internal set; } /// /// Gets or sets a value indicating whether this instance is reference. /// /// /// true if this instance is reference; otherwise, false. /// [Storable] public bool IsReference { get; internal set; } [StorableConstructor] protected TypeName(bool deserializing) { } /// /// Initializes a new instance of the class. /// /// The namespace. /// Name of the class. internal TypeName(string nameSpace, string className) { Namespace = nameSpace; ClassName = className; GenericArgs = new List(); MemoryMagic = ""; AssemblyAttribues = new Dictionary(); } /// /// Returns a that represents this instance. /// /// if set to true includes full information /// about generic parameters and assembly properties. /// /// A that represents this instance. /// public string ToString(bool full) { return ToString(full, true); } /// /// Returns a that represents this instance. /// /// if set to true includes full information /// about generic parameters and assembly properties. /// if set to true include assembly properties and generic parameters. /// /// A that represents this instance. /// public string ToString(bool full, bool includeAssembly) { StringBuilder sb = new StringBuilder(); if (!string.IsNullOrEmpty(Namespace)) sb.Append(Namespace).Append('.'); sb.Append(ClassName); if (IsGeneric) { sb.Append('`').Append(GenericArgs.Count).Append('['); bool first = true; foreach (TypeName t in GenericArgs) { if (first) first = false; else sb.Append(','); sb.Append('[').Append(t.ToString(full)).Append(']'); } sb.Append(']'); } sb.Append(MemoryMagic); if (includeAssembly && AssemblyName != null) { sb.Append(", ").Append(AssemblyName); if (full) foreach (var property in AssemblyAttribues) sb.Append(", ").Append(property.Key).Append('=').Append(property.Value); } return sb.ToString(); } public string GetTypeNameInCode(HashSet omitNamespaces) { StringBuilder sb = new StringBuilder(); if (!string.IsNullOrEmpty(Namespace) && omitNamespaces == null || !omitNamespaces.Contains(Namespace)) sb.Append(Namespace).Append('.'); sb.Append(ClassName); if (IsGeneric) { sb.Append("<"); sb.Append( string.Join(", ", GenericArgs .Select(a => a.GetTypeNameInCode(omitNamespaces)) .ToArray())); sb.Append(">"); } sb.Append(MemoryMagic); return sb.ToString(); } public string GetTypeNameInCode(bool includeAllNamespaces) { StringBuilder sb = new StringBuilder(); if (includeAllNamespaces) sb.Append(Namespace).Append('.'); sb.Append(ClassName); if (IsGeneric) { sb.Append("<"); sb.Append( string.Join(", ", GenericArgs .Select(a => a.GetTypeNameInCode(includeAllNamespaces)) .ToArray())); sb.Append(">"); } sb.Append(MemoryMagic); return sb.ToString(); } /// /// Returns a that represents this instance. /// /// /// A that represents this instance. /// public override string ToString() { return ToString(true); } /// /// Lexicographically compare version information and make sure type and assembly /// names are identical. This function recursively checks generic type arguments. /// /// Name of the type. /// /// true if is newer than the specified type name; otherwise, false. /// 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 thisIt = this.GenericArgs.GetEnumerator(); IEnumerator 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"); } } /// /// Make sure major and minor version number are identical. This function /// recursively checks generic type arguments. /// /// Name of the type. /// /// true if the specified type names are compatible; otherwise, false. /// 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 thisIt = this.GenericArgs.GetEnumerator(); IEnumerator 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"); } } private static int CompareVersions(string v1string, string v2string) { return new Version(v1string).CompareTo(new Version(v2string)); } } }