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
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2012 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
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;
23using System.Collections.Generic;
24using System.Linq;
25using System.Text;
26using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
27
28namespace HeuristicLab.Persistence.Auxiliary {
29
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>
35  [StorableClass]
36  public class TypeName {
37
38    /// <summary>
39    /// Gets or sets the namespace.
40    /// </summary>
41    /// <value>The namespace.</value>
42    [Storable]
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
47
48    /// <summary>
49    /// Gets or sets the name of the class.
50    /// </summary>
51    /// <value>The name of the class.</value>
52    [Storable]
53    #region Mono Compatibility
54    public string ClassName { get; internal set; }
55    #endregion
56
57    /// <summary>
58    /// Gets or sets the generic args.
59    /// </summary>
60    /// <value>The generic args.</value>
61    [Storable]
62    public List<TypeName> GenericArgs { get; internal set; }
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>
70    public bool IsGeneric { get { return GenericArgs.Count > 0; } }
71
72    /// <summary>
73    /// Gets or sets the memory magic (point or array declaration).
74    /// </summary>
75    /// <value>The memory magic.</value>
76    [Storable]
77    public string MemoryMagic { get; internal set; }
78
79    /// <summary>
80    /// Gets or sets the name of the assembly.
81    /// </summary>
82    /// <value>The name of the assembly.</value>
83    [Storable]
84    public string AssemblyName { get; internal set; }
85
86    /// <summary>
87    /// Gets or sets the assembly attribues.
88    /// </summary>
89    /// <value>The assembly attribues.</value>
90    [Storable]
91    public Dictionary<string, string> AssemblyAttribues { get; internal set; }
92
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>
99    [Storable]
100    public bool IsReference { get; internal set; }
101
102
103    [StorableConstructor]
104    protected TypeName(bool deserializing) { }
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>
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>();
116    }
117
118
119    /// <summary>
120    /// Returns a <see cref="System.String"/> that represents this instance.
121    /// </summary>
122    /// <param name="full">if set to <c>true</c> includes full information
123    /// about generic parameters and assembly properties.</param>
124    /// <returns>
125    /// A <see cref="System.String"/> that represents this instance.
126    /// </returns>
127    public string ToString(bool full) {
128      return ToString(full, true);
129    }
130
131
132    /// <summary>
133    /// Returns a <see cref="System.String"/> that represents this instance.
134    /// </summary>
135    /// <param name="full">if set to <c>true</c> includes full information
136    /// about generic parameters and assembly properties.</param>
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>
141    public string ToString(bool full, bool includeAssembly) {
142      StringBuilder sb = new StringBuilder();
143      if (!string.IsNullOrEmpty(Namespace))
144        sb.Append(Namespace).Append('.');
145      sb.Append(ClassName);
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(']');
157      }
158      sb.Append(MemoryMagic);
159      if (includeAssembly && AssemblyName != null) {
160        sb.Append(", ").Append(AssemblyName);
161        if (full)
162          foreach (var property in AssemblyAttribues)
163            sb.Append(", ").Append(property.Key).Append('=').Append(property.Value);
164      }
165      return sb.ToString();
166    }
167
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      }
182      sb.Append(MemoryMagic);
183      return sb.ToString();
184    }
185
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    }
203
204
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>
211    public override string ToString() {
212      return ToString(true);
213    }
214
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.
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>
224    public bool IsNewerThan(TypeName typeName) {
225      try {
226        if (this.ClassName != typeName.ClassName ||
227          this.Namespace != typeName.Namespace ||
228          this.AssemblyName != typeName.AssemblyName)
229          throw new Exception("Cannot compare versions of different types");
230        if (CompareVersions(
231          this.AssemblyAttribues["Version"],
232          typeName.AssemblyAttribues["Version"]) > 0)
233          return true;
234        IEnumerator<TypeName> thisIt = this.GenericArgs.GetEnumerator();
235        IEnumerator<TypeName> tIt = typeName.GenericArgs.GetEnumerator();
236        while (thisIt.MoveNext()) {
237          tIt.MoveNext();
238          if (thisIt.Current.IsNewerThan(tIt.Current))
239            return true;
240        }
241        return false;
242      }
243      catch (KeyNotFoundException) {
244        throw new Exception("Could not extract version information from type string");
245      }
246    }
247
248
249    /// <summary>
250    /// Make sure major and minor version number are identical. This function
251    /// recursively checks generic type arguments.
252    /// </summary>
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>
257    public bool IsCompatible(TypeName typeName) {
258      try {
259        if (this.ClassName != typeName.ClassName ||
260          this.Namespace != typeName.Namespace ||
261          this.AssemblyName != typeName.AssemblyName)
262          throw new Exception("Cannot compare versions of different types");
263        Version thisVersion = new Version(this.AssemblyAttribues["Version"]);
264        Version tVersion = new Version(typeName.AssemblyAttribues["Version"]);
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)
271          return false;
272        IEnumerator<TypeName> thisIt = this.GenericArgs.GetEnumerator();
273        IEnumerator<TypeName> tIt = typeName.GenericArgs.GetEnumerator();
274        while (thisIt.MoveNext()) {
275          tIt.MoveNext();
276          if (!thisIt.Current.IsCompatible(tIt.Current))
277            return false;
278        }
279        return true;
280      }
281      catch (KeyNotFoundException) {
282        throw new Exception("Could not extract version infomration from type string");
283      }
284    }
285
286    private static int CompareVersions(string v1string, string v2string) {
287      return new Version(v1string).CompareTo(new Version(v2string));
288    }
289  }
290}
Note: See TracBrowser for help on using the repository browser.