Free cookie consent management tool by TermsFeed Policy Generator

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

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

#1952 implemented reviewing comments

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