diff --git a/CHANGELOG.md b/CHANGELOG.md
index 825f45d..65ec3d2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,3 +3,16 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
+
+## [Unreleased]
+
+## [3.0.0] - 2018-04-23
+### Added
+ - Adding extension method for getting Informational Version from an Assembly
+ - Adding WeakKeyDictionary for caching
+ - Reflection util methods
+
+### Changed
+ - JSON serialization/deserialization features moved into base converter
+ - Removed suffix from assembly name
+
\ No newline at end of file
diff --git a/ICD.Common.Utils/AttributeUtils.cs b/ICD.Common.Utils/AttributeUtils.cs
index e9cf173..637b8cc 100644
--- a/ICD.Common.Utils/AttributeUtils.cs
+++ b/ICD.Common.Utils/AttributeUtils.cs
@@ -84,6 +84,14 @@ namespace ICD.Common.Utils
{
foreach (Exception inner in e.LoaderExceptions)
{
+ if (inner is System.IO.FileNotFoundException)
+ {
+ Logger.AddEntry(eSeverity.Error,
+ "{0} failed to cache assembly {1} - Could not find one or more dependencies by path",
+ typeof(AttributeUtils).Name, assembly.GetName().Name);
+ continue;
+ }
+
Logger.AddEntry(eSeverity.Error, inner, "{0} failed to cache assembly {1}", typeof(AttributeUtils).Name,
assembly.GetName().Name);
}
diff --git a/ICD.Common.Utils/Extensions/AssemblyExtensions.cs b/ICD.Common.Utils/Extensions/AssemblyExtensions.cs
index 3a67c37..fafd5a9 100644
--- a/ICD.Common.Utils/Extensions/AssemblyExtensions.cs
+++ b/ICD.Common.Utils/Extensions/AssemblyExtensions.cs
@@ -1,4 +1,5 @@
using System;
+using System.Linq;
using ICD.Common.Properties;
using ICD.Common.Utils.IO;
#if SIMPLSHARP
@@ -12,7 +13,7 @@ namespace ICD.Common.Utils.Extensions
public static class AssemblyExtensions
{
///
- /// Gets the path for the given assembly. Returns null if the assembly can not be found on disk.
+ /// Gets the path for the assembly. Returns null if the assembly can not be found on disk.
///
///
///
@@ -45,10 +46,11 @@ namespace ICD.Common.Utils.Extensions
}
///
- /// Gets the creation date of the given assembly.
+ /// Gets the creation date of the assembly.
///
///
///
+ [PublicAPI]
public static DateTime GetCreationTime(this Assembly extends)
{
if (extends == null)
@@ -57,5 +59,40 @@ namespace ICD.Common.Utils.Extensions
string path = extends.GetPath();
return path == null ? DateTime.MinValue : IcdFile.GetCreationTime(path);
}
+
+ ///
+ /// Gets the informational version for the assembly.
+ ///
+ ///
+ ///
+ [PublicAPI]
+ public static string GetInformationalVersion(this Assembly extends)
+ {
+ if (extends == null)
+ throw new ArgumentNullException("extends");
+
+ string version;
+ if (extends.TryGetInformationalVersion(out version))
+ return version;
+
+ throw new InvalidOperationException("Assembly has no informational version attribute.");
+ }
+
+ ///
+ /// Tries to get the informational version for the assembly.
+ ///
+ ///
+ ///
+ ///
+ [PublicAPI]
+ public static bool TryGetInformationalVersion(this Assembly extends, out string version)
+ {
+ if (extends == null)
+ throw new ArgumentNullException("extends");
+
+ return extends.GetCustomAttributes()
+ .Select(a => a.InformationalVersion)
+ .TryFirst(out version);
+ }
}
}
diff --git a/ICD.Common.Utils/Extensions/ListExtensions.cs b/ICD.Common.Utils/Extensions/ListExtensions.cs
index e5394a8..50c28c7 100644
--- a/ICD.Common.Utils/Extensions/ListExtensions.cs
+++ b/ICD.Common.Utils/Extensions/ListExtensions.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using ICD.Common.Properties;
+using ICD.Common.Utils.Comparers;
namespace ICD.Common.Utils.Extensions
{
@@ -29,7 +30,7 @@ namespace ICD.Common.Utils.Extensions
}
///
- /// Adds the item into a sorted list.
+ /// Adds the items into a sorted list.
///
///
///
@@ -50,6 +51,30 @@ namespace ICD.Common.Utils.Extensions
items.ForEach(i => extends.AddSorted(i, comparer));
}
+ ///
+ /// Adds the items into a sorted list.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ [PublicAPI]
+ public static void AddSorted(this List extends, IEnumerable items, Func predicate)
+ {
+ if (extends == null)
+ throw new ArgumentNullException("extends");
+
+ if (items == null)
+ throw new ArgumentNullException("items");
+
+ if (predicate == null)
+ throw new ArgumentNullException("predicate");
+
+ PredicateComparer comparer = new PredicateComparer(predicate);
+ extends.AddSorted(items, comparer);
+ }
+
///
/// Adds the item into a sorted list.
///
@@ -106,6 +131,27 @@ namespace ICD.Common.Utils.Extensions
extends.Insert(index, item);
}
+ ///
+ /// Adds the item into a sorted list.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ [PublicAPI]
+ public static void AddSorted(this List extends, T item, Func predicate)
+ {
+ if (extends == null)
+ throw new ArgumentNullException("extends");
+
+ if (predicate == null)
+ throw new ArgumentNullException("predicate");
+
+ PredicateComparer comparer = new PredicateComparer(predicate);
+ extends.AddSorted(item, comparer);
+ }
+
///
/// Pads the list to the given total length.
///
diff --git a/ICD.Common.Utils/IO/IcdPath.cs b/ICD.Common.Utils/IO/IcdPath.cs
index 37d0bad..6ee4a52 100644
--- a/ICD.Common.Utils/IO/IcdPath.cs
+++ b/ICD.Common.Utils/IO/IcdPath.cs
@@ -10,6 +10,10 @@ namespace ICD.Common.Utils.IO
{
public static class IcdPath
{
+ public static char DirectorySeparatorChar { get { return Path.DirectorySeparatorChar; } }
+
+ public static char AltDirectorySeparatorChar { get { return Path.AltDirectorySeparatorChar; } }
+
public static string GetFileName(string path)
{
if (path == null)
diff --git a/ICD.Common.Utils/Json/AbstractGenericJsonConverter.cs b/ICD.Common.Utils/Json/AbstractGenericJsonConverter.cs
index 151a7ca..ced8956 100644
--- a/ICD.Common.Utils/Json/AbstractGenericJsonConverter.cs
+++ b/ICD.Common.Utils/Json/AbstractGenericJsonConverter.cs
@@ -6,6 +6,15 @@ namespace ICD.Common.Utils.Json
{
public abstract class AbstractGenericJsonConverter : JsonConverter
{
+ ///
+ /// Creates a new instance of T.
+ ///
+ ///
+ protected virtual T Instantiate()
+ {
+ return ReflectionUtils.CreateInstance();
+ }
+
///
/// Writes the JSON representation of the object.
///
@@ -36,7 +45,24 @@ namespace ICD.Common.Utils.Json
/// The value.
/// The calling serializer.
[PublicAPI]
- public abstract void WriteJson(JsonWriter writer, T value, JsonSerializer serializer);
+ public virtual void WriteJson(JsonWriter writer, T value, JsonSerializer serializer)
+ {
+ writer.WriteStartObject();
+ {
+ WriteProperties(writer, value, serializer);
+ }
+ writer.WriteEndObject();
+ }
+
+ ///
+ /// Override to write properties to the writer.
+ ///
+ ///
+ ///
+ ///
+ protected virtual void WriteProperties(JsonWriter writer, T value, JsonSerializer serializer)
+ {
+ }
///
/// Reads the JSON representation of the object.
@@ -70,7 +96,52 @@ namespace ICD.Common.Utils.Json
/// The object value.
///
[PublicAPI]
- public abstract T ReadJson(JsonReader reader, T existingValue, JsonSerializer serializer);
+ public virtual T ReadJson(JsonReader reader, T existingValue, JsonSerializer serializer)
+ {
+ T output = default(T);
+ bool instantiated = false;
+
+ while (reader.Read())
+ {
+ if (reader.TokenType == JsonToken.Null || reader.TokenType == JsonToken.EndObject)
+ break;
+
+ if (!instantiated)
+ {
+ instantiated = true;
+ output = Instantiate();
+ }
+
+ // Get the property
+ if (reader.TokenType != JsonToken.PropertyName)
+ continue;
+ string property = (string)reader.Value;
+
+ // Read into the value
+ reader.Read();
+
+ switch (property)
+ {
+ default:
+ ReadProperty(property, reader, output, serializer);
+ break;
+ }
+ }
+
+ return output;
+ }
+
+ ///
+ /// Override to handle the current property value with the given name.
+ ///
+ ///
+ ///
+ ///
+ ///
+ protected virtual void ReadProperty(string property, JsonReader reader, T instance, JsonSerializer serializer)
+ {
+ reader.Skip();
+ }
///
/// Determines whether this instance can convert the specified object type.
diff --git a/ICD.Common.Utils/PathUtils.cs b/ICD.Common.Utils/PathUtils.cs
index 7a691e1..3d473a6 100644
--- a/ICD.Common.Utils/PathUtils.cs
+++ b/ICD.Common.Utils/PathUtils.cs
@@ -185,6 +185,24 @@ namespace ICD.Common.Utils
return IcdFile.Exists(path) || IcdDirectory.Exists(path);
}
+ ///
+ /// Returns the path if the given path is already a directory or has a trailing slash.
+ /// Otherwise returns the parent directory name.
+ ///
+ ///
+ ///
+ [PublicAPI]
+ public static string GetDirectoryNameFromPath(string path)
+ {
+ if (IcdDirectory.Exists(path))
+ return path;
+
+ if (path.EndsWith(IcdPath.DirectorySeparatorChar) || path.EndsWith(IcdPath.AltDirectorySeparatorChar))
+ return path;
+
+ return IcdPath.GetDirectoryName(path);
+ }
+
#endregion
}
}
diff --git a/ICD.Common.Utils/Properties/AssemblyInfo.cs b/ICD.Common.Utils/Properties/AssemblyInfo.cs
index 4a435e7..2303f51 100644
--- a/ICD.Common.Utils/Properties/AssemblyInfo.cs
+++ b/ICD.Common.Utils/Properties/AssemblyInfo.cs
@@ -4,4 +4,4 @@ using System.Reflection;
[assembly: AssemblyCompany("ICD Systems")]
[assembly: AssemblyProduct("ICD.Common.Utils")]
[assembly: AssemblyCopyright("Copyright © ICD Systems 2018")]
-[assembly: AssemblyVersion("2.0.0.0")]
+[assembly: AssemblyVersion("3.0.0.0")]
diff --git a/ICD.Common.Utils/StringUtils.cs b/ICD.Common.Utils/StringUtils.cs
index 36008e7..3235b7b 100644
--- a/ICD.Common.Utils/StringUtils.cs
+++ b/ICD.Common.Utils/StringUtils.cs
@@ -610,5 +610,77 @@ namespace ICD.Common.Utils
{
return value == null ? null : value.ToUpper();
}
+
+ ///
+ /// Compares the given chars for equality.
+ ///
+ ///
+ ///
+ ///
+ ///
+ [PublicAPI]
+ public static bool Compare(char a, char b, bool ignoreCase)
+ {
+ if (ignoreCase)
+ {
+ a = char.ToUpper(a, CultureInfo.InvariantCulture);
+ b = char.ToUpper(b, CultureInfo.InvariantCulture);
+ }
+
+ return a == b;
+ }
+
+ ///
+ /// Find the longest common string between the matches.
+ /// E.g.
+ ///
+ /// C:\\Workspace
+ /// C:\\Workshop
+ ///
+ /// Results in
+ ///
+ /// C:\\Work
+ ///
+ ///
+ ///
+ ///
+ [PublicAPI]
+ public static string GetLongestCommonIntersectionFromStart(IEnumerable items, bool ignoreCase)
+ {
+ if (items == null)
+ throw new ArgumentNullException("items");
+
+ string output = null;
+
+ foreach (string item in items)
+ {
+ // If there is a null in the sequence that's the best match we can make
+ if (string.IsNullOrEmpty(item))
+ return null;
+
+ // Seed our first item
+ if (output == null)
+ {
+ output = item;
+ continue;
+ }
+
+ // Find the common substring
+ for (int index = 0; index < output.Length; index++)
+ {
+ if (index >= item.Length || !Compare(output[index], item[index], ignoreCase))
+ {
+ output = output.Substring(0, index);
+ break;
+ }
+ }
+
+ // Abandon the search if there is no common substring
+ if (string.IsNullOrEmpty(output))
+ break;
+ }
+
+ return output;
+ }
}
}