Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Persistence/3.3/Auxiliary/TypeName.cs @ 8641

Last change on this file since 8641 was 8641, checked in by ascheibe, 12 years ago

#1952 (#1937) added Mono support to persistence

File size: 10.2 KB
RevLine 
[3743]1#region License Information
2/* HeuristicLab
[7259]3 * Copyright (C) 2002-2012 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
22using System;
[4068]23using System.Collections.Generic;
[3903]24using System.Linq;
[1703]25using System.Text;
[3004]26using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
[1703]27
28namespace HeuristicLab.Persistence.Auxiliary {
[3016]29
[3004]30  /// <summary>
31  /// Contains a more modular representation of type names that can
32  /// be used to compare versions and ignore extended assembly
33  /// attributes.
34  /// </summary>
[3017]35  [StorableClass]
[1776]36  public class TypeName {
[3004]37
[3016]38    /// <summary>
39    /// Gets or sets the namespace.
40    /// </summary>
41    /// <value>The namespace.</value>
[3004]42    [Storable]
[8641]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
[3004]47
[3016]48    /// <summary>
49    /// Gets or sets the name of the class.
50    /// </summary>
51    /// <value>The name of the class.</value>
[3004]52    [Storable]
[8641]53    #region Mono Compatibility
54    public string ClassName { get; internal set; }
55    #endregion
[3004]56
[3016]57    /// <summary>
58    /// Gets or sets the generic args.
59    /// </summary>
60    /// <value>The generic args.</value>
[3004]61    [Storable]
[1779]62    public List<TypeName> GenericArgs { get; internal set; }
[3036]63
64    /// <summary>
65    /// Gets a value indicating whether this instance is generic.
66    /// </summary>
67    /// <value>
68    ///   <c>true</c> if this instance is generic; otherwise, <c>false</c>.
69    /// </value>
[1776]70    public bool IsGeneric { get { return GenericArgs.Count > 0; } }
[3004]71
[3016]72    /// <summary>
73    /// Gets or sets the memory magic (point or array declaration).
74    /// </summary>
75    /// <value>The memory magic.</value>
[3004]76    [Storable]
[1779]77    public string MemoryMagic { get; internal set; }
[3004]78
[3016]79    /// <summary>
80    /// Gets or sets the name of the assembly.
81    /// </summary>
82    /// <value>The name of the assembly.</value>
[3004]83    [Storable]
[1779]84    public string AssemblyName { get; internal set; }
[3004]85
[3016]86    /// <summary>
87    /// Gets or sets the assembly attribues.
88    /// </summary>
89    /// <value>The assembly attribues.</value>
[3004]90    [Storable]
[1779]91    public Dictionary<string, string> AssemblyAttribues { get; internal set; }
[3004]92
[3016]93    /// <summary>
94    /// Gets or sets a value indicating whether this instance is reference.
95    /// </summary>
96    /// <value>
97    ///   <c>true</c> if this instance is reference; otherwise, <c>false</c>.
98    /// </value>
[3004]99    [Storable]
[1779]100    public bool IsReference { get; internal set; }
101
[3016]102
[4806]103    [StorableConstructor]
104    protected TypeName(bool deserializing) { }
[3016]105    /// <summary>
106    /// Initializes a new instance of the <see cref="TypeName"/> class.
107    /// </summary>
108    /// <param name="nameSpace">The namespace.</param>
109    /// <param name="className">Name of the class.</param>
[1779]110    internal TypeName(string nameSpace, string className) {
111      Namespace = nameSpace;
112      ClassName = className;
113      GenericArgs = new List<TypeName>();
114      MemoryMagic = "";
115      AssemblyAttribues = new Dictionary<string, string>();
[1776]116    }
117
[3016]118
119    /// <summary>
120    /// Returns a <see cref="System.String"/> that represents this instance.
121    /// </summary>
[3036]122    /// <param name="full">if set to <c>true</c> includes full information
[3016]123    /// about generic parameters and assembly properties.</param>
124    /// <returns>
125    /// A <see cref="System.String"/> that represents this instance.
126    /// </returns>
[1779]127    public string ToString(bool full) {
[1780]128      return ToString(full, true);
129    }
130
[3004]131
[3016]132    /// <summary>
133    /// Returns a <see cref="System.String"/> that represents this instance.
134    /// </summary>
[3036]135    /// <param name="full">if set to <c>true</c> includes full information
136    /// about generic parameters and assembly properties.</param>
[3016]137    /// <param name="includeAssembly">if set to <c>true</c> include assembly properties and generic parameters.</param>
138    /// <returns>
139    /// A <see cref="System.String"/> that represents this instance.
140    /// </returns>
[4068]141    public string ToString(bool full, bool includeAssembly) {
[1779]142      StringBuilder sb = new StringBuilder();
[2859]143      if (!string.IsNullOrEmpty(Namespace))
144        sb.Append(Namespace).Append('.');
145      sb.Append(ClassName);
[1779]146      if (IsGeneric) {
147        sb.Append('`').Append(GenericArgs.Count).Append('[');
148        bool first = true;
149        foreach (TypeName t in GenericArgs) {
150          if (first)
151            first = false;
152          else
153            sb.Append(',');
154          sb.Append('[').Append(t.ToString(full)).Append(']');
155        }
156        sb.Append(']');
[1703]157      }
[1779]158      sb.Append(MemoryMagic);
[1780]159      if (includeAssembly && AssemblyName != null) {
[1779]160        sb.Append(", ").Append(AssemblyName);
[1780]161        if (full)
162          foreach (var property in AssemblyAttribues)
163            sb.Append(", ").Append(property.Key).Append('=').Append(property.Value);
164      }
[1779]165      return sb.ToString();
[1703]166    }
167
[3903]168    public string GetTypeNameInCode(HashSet<string> omitNamespaces) {
169      StringBuilder sb = new StringBuilder();
170      if (!string.IsNullOrEmpty(Namespace) && omitNamespaces == null || !omitNamespaces.Contains(Namespace))
171        sb.Append(Namespace).Append('.');
172      sb.Append(ClassName);
173      if (IsGeneric) {
174        sb.Append("<");
175        sb.Append(
176          string.Join(", ",
177            GenericArgs
178              .Select(a => a.GetTypeNameInCode(omitNamespaces))
179              .ToArray()));
180        sb.Append(">");
181      }
[3935]182      sb.Append(MemoryMagic);
[3903]183      return sb.ToString();
184    }
[3016]185
[3935]186    public string GetTypeNameInCode(bool includeAllNamespaces) {
187      StringBuilder sb = new StringBuilder();
188      if (includeAllNamespaces)
189        sb.Append(Namespace).Append('.');
190      sb.Append(ClassName);
191      if (IsGeneric) {
192        sb.Append("<");
193        sb.Append(
194          string.Join(", ",
195            GenericArgs
196              .Select(a => a.GetTypeNameInCode(includeAllNamespaces))
197              .ToArray()));
198        sb.Append(">");
199      }
200      sb.Append(MemoryMagic);
201      return sb.ToString();
202    }
[3903]203
[3935]204
[3016]205    /// <summary>
206    /// Returns a <see cref="System.String"/> that represents this instance.
207    /// </summary>
208    /// <returns>
209    /// A <see cref="System.String"/> that represents this instance.
210    /// </returns>
[1779]211    public override string ToString() {
212      return ToString(true);
213    }
214
[3004]215
216    /// <summary>
217    /// Lexicographically compare version information and make sure type and assembly
218    /// names are identical. This function recursively checks generic type arguments.
[3016]219    /// </summary>
220    /// <param name="typeName">Name of the type.</param>
221    /// <returns>
222    ///   <c>true</c> if is newer than the specified type name; otherwise, <c>false</c>.
223    /// </returns>
[3004]224    public bool IsNewerThan(TypeName typeName) {
[1780]225      try {
[3004]226        if (this.ClassName != typeName.ClassName ||
227          this.Namespace != typeName.Namespace ||
228          this.AssemblyName != typeName.AssemblyName)
[1780]229          throw new Exception("Cannot compare versions of different types");
230        if (CompareVersions(
231          this.AssemblyAttribues["Version"],
[3004]232          typeName.AssemblyAttribues["Version"]) > 0)
[1779]233          return true;
[1780]234        IEnumerator<TypeName> thisIt = this.GenericArgs.GetEnumerator();
[3004]235        IEnumerator<TypeName> tIt = typeName.GenericArgs.GetEnumerator();
[1780]236        while (thisIt.MoveNext()) {
237          tIt.MoveNext();
[1795]238          if (thisIt.Current.IsNewerThan(tIt.Current))
[1780]239            return true;
240        }
241        return false;
[8641]242      }
243      catch (KeyNotFoundException) {
[1780]244        throw new Exception("Could not extract version information from type string");
[1703]245      }
246    }
247
[3004]248
249    /// <summary>
250    /// Make sure major and minor version number are identical. This function
251    /// recursively checks generic type arguments.
252    /// </summary>
[3016]253    /// <param name="typeName">Name of the type.</param>
254    /// <returns>
255    ///   <c>true</c> if the specified type names are compatible; otherwise, <c>false</c>.
256    /// </returns>
[3004]257    public bool IsCompatible(TypeName typeName) {
[1795]258      try {
[3004]259        if (this.ClassName != typeName.ClassName ||
260          this.Namespace != typeName.Namespace ||
261          this.AssemblyName != typeName.AssemblyName)
[1795]262          throw new Exception("Cannot compare versions of different types");
263        Version thisVersion = new Version(this.AssemblyAttribues["Version"]);
[3004]264        Version tVersion = new Version(typeName.AssemblyAttribues["Version"]);
[5172]265        if (this.AssemblyName == "mscorlib" &&
266          (thisVersion.Major == 2 || thisVersion.Major == 4) &&
267          (tVersion.Major == 2 || tVersion.Major == 4)) {
268          // skip version check
269        } else if (thisVersion.Major != tVersion.Major ||
270                   thisVersion.Minor != tVersion.Minor)
[1795]271          return false;
272        IEnumerator<TypeName> thisIt = this.GenericArgs.GetEnumerator();
[3004]273        IEnumerator<TypeName> tIt = typeName.GenericArgs.GetEnumerator();
[1795]274        while (thisIt.MoveNext()) {
275          tIt.MoveNext();
276          if (!thisIt.Current.IsCompatible(tIt.Current))
277            return false;
278        }
279        return true;
[8641]280      }
281      catch (KeyNotFoundException) {
[1795]282        throw new Exception("Could not extract version infomration from type string");
283      }
284    }
285
[1779]286    private static int CompareVersions(string v1string, string v2string) {
287      return new Version(v1string).CompareTo(new Version(v2string));
[1776]288    }
[1703]289  }
290}
Note: See TracBrowser for help on using the repository browser.