#region License Information
/* HeuristicLab
* Copyright (C) 2002-2012 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));
}
}
}