mirror of
https://github.com/ICDSystems/ICD.Common.Utils.git
synced 2026-02-07 08:45:12 +00:00
Merge branch 'dev' of https://cs-gogs.icdpf.net/Common/Utils into dev
This commit is contained in:
13
CHANGELOG.md
13
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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
@@ -45,10 +46,11 @@ namespace ICD.Common.Utils.Extensions
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the creation date of the given assembly.
|
||||
/// Gets the creation date of the assembly.
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
[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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the informational version for the assembly.
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
[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.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to get the informational version for the assembly.
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="version"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static bool TryGetInformationalVersion(this Assembly extends, out string version)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
return extends.GetCustomAttributes<AssemblyInformationalVersionAttribute>()
|
||||
.Select(a => a.InformationalVersion)
|
||||
.TryFirst(out version);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the item into a sorted list.
|
||||
/// Adds the items into a sorted list.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="extends"></param>
|
||||
@@ -50,6 +51,30 @@ namespace ICD.Common.Utils.Extensions
|
||||
items.ForEach(i => extends.AddSorted(i, comparer));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the items into a sorted list.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <typeparam name="TProp"></typeparam>
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="items"></param>
|
||||
/// <param name="predicate"></param>
|
||||
[PublicAPI]
|
||||
public static void AddSorted<T, TProp>(this List<T> extends, IEnumerable<T> items, Func<T, TProp> predicate)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
if (items == null)
|
||||
throw new ArgumentNullException("items");
|
||||
|
||||
if (predicate == null)
|
||||
throw new ArgumentNullException("predicate");
|
||||
|
||||
PredicateComparer<T, TProp> comparer = new PredicateComparer<T, TProp>(predicate);
|
||||
extends.AddSorted(items, comparer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the item into a sorted list.
|
||||
/// </summary>
|
||||
@@ -106,6 +131,27 @@ namespace ICD.Common.Utils.Extensions
|
||||
extends.Insert(index, item);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the item into a sorted list.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <typeparam name="TProp"></typeparam>
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="item"></param>
|
||||
/// <param name="predicate"></param>
|
||||
[PublicAPI]
|
||||
public static void AddSorted<T, TProp>(this List<T> extends, T item, Func<T, TProp> predicate)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
if (predicate == null)
|
||||
throw new ArgumentNullException("predicate");
|
||||
|
||||
PredicateComparer<T, TProp> comparer = new PredicateComparer<T, TProp>(predicate);
|
||||
extends.AddSorted(item, comparer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pads the list to the given total length.
|
||||
/// </summary>
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -6,6 +6,15 @@ namespace ICD.Common.Utils.Json
|
||||
{
|
||||
public abstract class AbstractGenericJsonConverter<T> : JsonConverter
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new instance of T.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected virtual T Instantiate()
|
||||
{
|
||||
return ReflectionUtils.CreateInstance<T>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the JSON representation of the object.
|
||||
/// </summary>
|
||||
@@ -36,7 +45,24 @@ namespace ICD.Common.Utils.Json
|
||||
/// <param name="value">The value.</param>
|
||||
/// <param name="serializer">The calling serializer.</param>
|
||||
[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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override to write properties to the writer.
|
||||
/// </summary>
|
||||
/// <param name="writer"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="serializer"></param>
|
||||
protected virtual void WriteProperties(JsonWriter writer, T value, JsonSerializer serializer)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the JSON representation of the object.
|
||||
@@ -70,7 +96,52 @@ namespace ICD.Common.Utils.Json
|
||||
/// The object value.
|
||||
/// </returns>
|
||||
[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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override to handle the current property value with the given name.
|
||||
/// </summary>
|
||||
/// <param name="property"></param>
|
||||
/// <param name="reader"></param>
|
||||
/// <param name="instance"></param>
|
||||
/// <param name="serializer"></param>
|
||||
protected virtual void ReadProperty(string property, JsonReader reader, T instance, JsonSerializer serializer)
|
||||
{
|
||||
reader.Skip();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether this instance can convert the specified object type.
|
||||
|
||||
@@ -185,6 +185,24 @@ namespace ICD.Common.Utils
|
||||
return IcdFile.Exists(path) || IcdDirectory.Exists(path);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the path if the given path is already a directory or has a trailing slash.
|
||||
/// Otherwise returns the parent directory name.
|
||||
/// </summary>
|
||||
/// <param name="path"></param>
|
||||
/// <returns></returns>
|
||||
[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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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")]
|
||||
|
||||
@@ -610,5 +610,77 @@ namespace ICD.Common.Utils
|
||||
{
|
||||
return value == null ? null : value.ToUpper();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compares the given chars for equality.
|
||||
/// </summary>
|
||||
/// <param name="a"></param>
|
||||
/// <param name="b"></param>
|
||||
/// <param name="ignoreCase"></param>
|
||||
/// <returns></returns>
|
||||
[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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Find the longest common string between the matches.
|
||||
/// E.g.
|
||||
///
|
||||
/// C:\\Workspace
|
||||
/// C:\\Workshop
|
||||
///
|
||||
/// Results in
|
||||
///
|
||||
/// C:\\Work
|
||||
/// </summary>
|
||||
/// <param name="items"></param>
|
||||
/// <param name="ignoreCase"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static string GetLongestCommonIntersectionFromStart(IEnumerable<string> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user