From 29e1ef82bb3c30fcfff63516e398babfd7730f63 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Thu, 15 Feb 2018 14:44:21 -0500 Subject: [PATCH 01/12] Extension method for writing a Type as a JSON value --- ICD.Common.Utils/Extensions/JsonExtensions.cs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/ICD.Common.Utils/Extensions/JsonExtensions.cs b/ICD.Common.Utils/Extensions/JsonExtensions.cs index 22ca920..0d9ce11 100644 --- a/ICD.Common.Utils/Extensions/JsonExtensions.cs +++ b/ICD.Common.Utils/Extensions/JsonExtensions.cs @@ -34,6 +34,21 @@ namespace ICD.Common.Utils.Extensions jObject.WriteTo(extends, converter); } + /// + /// Writes the type value. + /// + /// + /// + [PublicAPI] + public static void WriteType(this JsonWriter extends, Type type) + { + if (extends == null) + throw new ArgumentNullException("extends"); + + string assemblyName = type == null ? null : type.AssemblyQualifiedName; + extends.WriteValue(assemblyName); + } + /// /// Gets the current value as an integer. /// From 45d88b1efbb7a924fd412fb020012bdde96bffd0 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Thu, 15 Feb 2018 15:05:15 -0500 Subject: [PATCH 02/12] Slightly lighter JSON --- ICD.Common.Utils/Extensions/JsonExtensions.cs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/ICD.Common.Utils/Extensions/JsonExtensions.cs b/ICD.Common.Utils/Extensions/JsonExtensions.cs index 0d9ce11..42834c9 100644 --- a/ICD.Common.Utils/Extensions/JsonExtensions.cs +++ b/ICD.Common.Utils/Extensions/JsonExtensions.cs @@ -45,8 +45,16 @@ namespace ICD.Common.Utils.Extensions if (extends == null) throw new ArgumentNullException("extends"); - string assemblyName = type == null ? null : type.AssemblyQualifiedName; - extends.WriteValue(assemblyName); + string name; + + if (type == null) + name = null; + else if (type.IsPrimitive) + name = type.Name; + else + name = type.AssemblyQualifiedName; + + extends.WriteValue(name); } /// From ee03f85704f9bfa20f8fb3455c6c9fecdf372368 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Thu, 15 Feb 2018 16:34:25 -0500 Subject: [PATCH 03/12] Removing bad token type check from AbstractGenericJsonConverter --- .../Json/AbstractGenericJsonConverterTest.cs | 13 +++++++++++++ .../Json/AbstractGenericJsonConverter.cs | 3 --- 2 files changed, 13 insertions(+), 3 deletions(-) create mode 100644 ICD.Common.Utils.Tests/Json/AbstractGenericJsonConverterTest.cs diff --git a/ICD.Common.Utils.Tests/Json/AbstractGenericJsonConverterTest.cs b/ICD.Common.Utils.Tests/Json/AbstractGenericJsonConverterTest.cs new file mode 100644 index 0000000..c43fd6d --- /dev/null +++ b/ICD.Common.Utils.Tests/Json/AbstractGenericJsonConverterTest.cs @@ -0,0 +1,13 @@ +using NUnit.Framework; + +namespace ICD.Common.Utils.Tests.Json +{ + public abstract class AbstractGenericJsonConverterTest + { + [Test] + public abstract void WriteJsonTest(); + + [Test] + public abstract void ReadJsonTest(); + } +} diff --git a/ICD.Common.Utils/Json/AbstractGenericJsonConverter.cs b/ICD.Common.Utils/Json/AbstractGenericJsonConverter.cs index 900b1ce..31a2a6e 100644 --- a/ICD.Common.Utils/Json/AbstractGenericJsonConverter.cs +++ b/ICD.Common.Utils/Json/AbstractGenericJsonConverter.cs @@ -45,9 +45,6 @@ namespace ICD.Common.Utils.Json public sealed override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { - if (reader.TokenType == JsonToken.Null) - return null; - return ReadJson(reader, (T)existingValue, serializer); } From 220f746d215c95c3a6694153c9b127d747366a3e Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Fri, 16 Feb 2018 11:50:26 -0500 Subject: [PATCH 04/12] Extensions for serializing/deserializing arrays and dicts to/from JSON --- ICD.Common.Utils/Extensions/JsonExtensions.cs | 125 ++++++++++++++++++ 1 file changed, 125 insertions(+) diff --git a/ICD.Common.Utils/Extensions/JsonExtensions.cs b/ICD.Common.Utils/Extensions/JsonExtensions.cs index 42834c9..5721159 100644 --- a/ICD.Common.Utils/Extensions/JsonExtensions.cs +++ b/ICD.Common.Utils/Extensions/JsonExtensions.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using ICD.Common.Properties; using Newtonsoft.Json; using Newtonsoft.Json.Linq; @@ -126,5 +127,129 @@ namespace ICD.Common.Utils.Extensions return EnumUtils.Parse(extends.GetValueAsString(), true); return (T)(object)extends.GetValueAsInt(); } + + /// + /// Serializes the given sequence of items to the writer. + /// + /// + /// + /// + /// + public static void SerializeArray(this JsonSerializer extends, JsonWriter writer, IEnumerable items) + { + if (extends == null) + throw new ArgumentNullException("extends"); + + if (writer == null) + throw new ArgumentNullException("writer"); + + if (items == null) + throw new ArgumentNullException("items"); + + writer.WriteStartArray(); + { + foreach (TItem item in items) + extends.Serialize(writer, item); + } + writer.WriteEndArray(); + } + + /// + /// Deserializes an array of items from the reader's current value. + /// + /// + /// + /// + public static IEnumerable DeserializeArray(this JsonSerializer extends, JsonReader reader) + { + if (extends == null) + throw new ArgumentNullException("extends"); + + if (reader == null) + throw new ArgumentNullException("reader"); + + if (reader.TokenType == JsonToken.Null) + yield break; + + if (reader.TokenType != JsonToken.StartArray) + throw new FormatException(string.Format("Expected token {0} got {1}", JsonToken.StartArray, reader.TokenType)); + + // Step into the first value + reader.Read(); + + while (reader.TokenType != JsonToken.EndArray) + { + TItem output = extends.Deserialize(reader); + yield return output; + } + } + + /// + /// Serializes the given sequence of key-value-pairs to the writer. + /// + /// + /// + /// + /// + /// + public static void SerializeDictionary(this JsonSerializer extends, JsonWriter writer, + IEnumerable> items) + { + if (extends == null) + throw new ArgumentNullException("extends"); + + if (writer == null) + throw new ArgumentNullException("writer"); + + if (items == null) + throw new ArgumentNullException("items"); + + writer.WriteStartObject(); + { + foreach (KeyValuePair kvp in items) + { + writer.WritePropertyName(kvp.Key.ToString()); + extends.Serialize(writer, kvp.Value); + } + } + writer.WriteEndObject(); + } + + /// + /// Deserializes a dictionary of items from the reader's current value. + /// + /// + /// + /// + /// + public static IEnumerable> DeserializeDictionary(this JsonSerializer extends, JsonReader reader) + { + if (extends == null) + throw new ArgumentNullException("extends"); + + if (reader == null) + throw new ArgumentNullException("reader"); + + if (reader.TokenType == JsonToken.Null) + yield break; + + if (reader.TokenType != JsonToken.StartObject) + throw new FormatException(string.Format("Expected token {0} got {1}", JsonToken.StartObject, reader.TokenType)); + + // Step into the first key + reader.Read(); + + while (reader.TokenType != JsonToken.EndObject) + { + TKey key = (TKey)Convert.ChangeType(reader.Value, typeof(TKey)); + + // Step into the value + reader.Read(); + + TValue value = extends.Deserialize(reader); + + yield return new KeyValuePair(key, value); + } + } } } From e308259a4449c2713f06f08693db92afa567795b Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Fri, 16 Feb 2018 13:36:09 -0500 Subject: [PATCH 05/12] Fixing SimplSharp build --- ICD.Common.Utils/Extensions/JsonExtensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ICD.Common.Utils/Extensions/JsonExtensions.cs b/ICD.Common.Utils/Extensions/JsonExtensions.cs index 5721159..92da75c 100644 --- a/ICD.Common.Utils/Extensions/JsonExtensions.cs +++ b/ICD.Common.Utils/Extensions/JsonExtensions.cs @@ -241,7 +241,7 @@ namespace ICD.Common.Utils.Extensions while (reader.TokenType != JsonToken.EndObject) { - TKey key = (TKey)Convert.ChangeType(reader.Value, typeof(TKey)); + TKey key = (TKey)Convert.ChangeType(reader.Value, typeof(TKey), null); // Step into the value reader.Read(); From a710e4f052ac04de47cb32c52eefa57fce28391e Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Fri, 16 Feb 2018 13:36:22 -0500 Subject: [PATCH 06/12] Catching stupid Crestron exception --- ICD.Common.Utils/Extensions/ReflectionExtensions.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/ICD.Common.Utils/Extensions/ReflectionExtensions.cs b/ICD.Common.Utils/Extensions/ReflectionExtensions.cs index 79f344b..7986791 100644 --- a/ICD.Common.Utils/Extensions/ReflectionExtensions.cs +++ b/ICD.Common.Utils/Extensions/ReflectionExtensions.cs @@ -42,7 +42,15 @@ namespace ICD.Common.Utils.Extensions if (extends == null) throw new ArgumentNullException("extends"); - return extends.GetCustomAttributes(typeof(T), inherits).Cast(); + try + { + return extends.GetCustomAttributes(typeof(T), inherits).Cast(); + } + // Crestron bug? + catch (ArgumentNullException) + { + return Enumerable.Empty(); + } } /// From b62b5661e5aa3121a40c6b2ee7fa2dc3ddad4128 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Fri, 16 Feb 2018 14:39:43 -0500 Subject: [PATCH 07/12] Util method to cache a Type for JSON serialization --- ICD.Common.Utils/Json/JsonUtils.cs | 12 ++++++++++-- ICD.Common.Utils/ReflectionUtils.cs | 20 ++++++++++++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/ICD.Common.Utils/Json/JsonUtils.cs b/ICD.Common.Utils/Json/JsonUtils.cs index 2e0a46b..4b49dfe 100644 --- a/ICD.Common.Utils/Json/JsonUtils.cs +++ b/ICD.Common.Utils/Json/JsonUtils.cs @@ -29,8 +29,16 @@ namespace ICD.Common.Utils.Json public static void CacheType() where T : new() { - string serialized = JsonConvert.SerializeObject(ReflectionUtils.CreateInstance()); - JsonConvert.DeserializeObject(serialized); + CacheType(typeof(T)); + } + + /// + /// Forces Newtonsoft to cache the given type for faster subsequent usage. + /// + public static void CacheType(Type type) + { + string serialized = JsonConvert.SerializeObject(ReflectionUtils.CreateInstance(type)); + JsonConvert.DeserializeObject(serialized, type); } /// diff --git a/ICD.Common.Utils/ReflectionUtils.cs b/ICD.Common.Utils/ReflectionUtils.cs index 0aaeab0..2cd7c36 100644 --- a/ICD.Common.Utils/ReflectionUtils.cs +++ b/ICD.Common.Utils/ReflectionUtils.cs @@ -210,6 +210,26 @@ namespace ICD.Common.Utils : null; } + /// + /// Returns true if the given type has a public parameterless constructor. + /// + /// + /// + public static bool HasPublicParameterlessConstructor(Type type) + { + if (type == null) + throw new ArgumentNullException("type"); + + const BindingFlags binding = BindingFlags.Instance | BindingFlags.Public; + +#if SIMPLSHARP + return ((CType)type).GetConstructor(binding, null, new CType[0], null) +#else + return type.GetConstructor(binding, null, new Type[0], null) +#endif + != null; + } + /// /// Creates an instance of the given type, calling the default constructor. /// From 41d0a43effb41a279cd1bf4fb2d316bf243ef5eb Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Sat, 17 Feb 2018 12:44:10 -0500 Subject: [PATCH 08/12] Fixing bug where array/dictionary deserialization was never terminating --- .../Extensions/JsonExtensionsTest.cs | 94 ++++++++++++++++++- ICD.Common.Utils/Extensions/JsonExtensions.cs | 6 ++ 2 files changed, 99 insertions(+), 1 deletion(-) diff --git a/ICD.Common.Utils.Tests/Extensions/JsonExtensionsTest.cs b/ICD.Common.Utils.Tests/Extensions/JsonExtensionsTest.cs index 7327c7f..b759053 100644 --- a/ICD.Common.Utils.Tests/Extensions/JsonExtensionsTest.cs +++ b/ICD.Common.Utils.Tests/Extensions/JsonExtensionsTest.cs @@ -1,4 +1,10 @@ -using NUnit.Framework; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using ICD.Common.Utils.Extensions; +using Newtonsoft.Json; +using NUnit.Framework; namespace ICD.Common.Utils.Tests.Extensions { @@ -34,5 +40,91 @@ namespace ICD.Common.Utils.Tests.Extensions { Assert.Inconclusive(); } + + [Test] + public void SerializeArrayTest() + { + JsonSerializer serializer = new JsonSerializer(); + StringBuilder stringBuilder = new StringBuilder(); + + using (StringWriter stringWriter = new StringWriter(stringBuilder)) + { + using (JsonWriter writer = new JsonTextWriter(stringWriter)) + { + serializer.SerializeArray(writer, new int[] {1, 2, 3, 4}); + } + } + + string json = stringBuilder.ToString(); + Assert.AreEqual("[1,2,3,4]", json); + } + + [Test] + public void DeserializeArrayTest() + { + const string json = "[1,2,3,4]"; + + JsonSerializer serializer = new JsonSerializer(); + int[] deserialized; + + using (StringReader stringReader = new StringReader(json)) + { + using (JsonReader reader = new JsonTextReader(stringReader)) + { + reader.Read(); + deserialized = serializer.DeserializeArray(reader).ToArray(); + } + } + + Assert.IsTrue(deserialized.SequenceEqual(new int[] {1, 2, 3, 4})); + } + + [Test] + public void SerializeDictionaryTest() + { + Dictionary dict = new Dictionary + { + {1, "Item 1"}, + {10, "Item 2"}, + {15, "Item 3"} + }; + + JsonSerializer serializer = new JsonSerializer(); + StringBuilder stringBuilder = new StringBuilder(); + + using (StringWriter stringWriter = new StringWriter(stringBuilder)) + { + using (JsonWriter writer = new JsonTextWriter(stringWriter)) + { + serializer.SerializeDictionary(writer, dict); + } + } + + string json = stringBuilder.ToString(); + Assert.AreEqual("{\"1\":\"Item 1\",\"10\":\"Item 2\",\"15\":\"Item 3\"}", json); + } + + [Test] + public void DeserializeDictionaryTest() + { + const string json = "{\"1\":\"Item 1\",\"10\":\"Item 2\",\"15\":\"Item 3\"}"; + + JsonSerializer serializer = new JsonSerializer(); + Dictionary deserialized; + + using (StringReader stringReader = new StringReader(json)) + { + using (JsonReader reader = new JsonTextReader(stringReader)) + { + reader.Read(); + deserialized = serializer.DeserializeDictionary(reader).ToDictionary(); + } + } + + Assert.AreEqual(3, deserialized.Count); + Assert.AreEqual("Item 1", deserialized[1]); + Assert.AreEqual("Item 2", deserialized[10]); + Assert.AreEqual("Item 3", deserialized[15]); + } } } diff --git a/ICD.Common.Utils/Extensions/JsonExtensions.cs b/ICD.Common.Utils/Extensions/JsonExtensions.cs index 92da75c..ed5338c 100644 --- a/ICD.Common.Utils/Extensions/JsonExtensions.cs +++ b/ICD.Common.Utils/Extensions/JsonExtensions.cs @@ -181,6 +181,9 @@ namespace ICD.Common.Utils.Extensions { TItem output = extends.Deserialize(reader); yield return output; + + // Read out of the last value + reader.Read(); } } @@ -249,6 +252,9 @@ namespace ICD.Common.Utils.Extensions TValue value = extends.Deserialize(reader); yield return new KeyValuePair(key, value); + + // Read out of the last value + reader.Read(); } } } From e07bffaf9095fabb96b9fdbb642d326ecec7ca6b Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Mon, 19 Feb 2018 11:00:42 -0500 Subject: [PATCH 09/12] Extension methods for further controlling JSON array serialization/deserialization --- ICD.Common.Utils/Extensions/JsonExtensions.cs | 67 ++++++++++++++++++- 1 file changed, 65 insertions(+), 2 deletions(-) diff --git a/ICD.Common.Utils/Extensions/JsonExtensions.cs b/ICD.Common.Utils/Extensions/JsonExtensions.cs index ed5338c..be15396 100644 --- a/ICD.Common.Utils/Extensions/JsonExtensions.cs +++ b/ICD.Common.Utils/Extensions/JsonExtensions.cs @@ -58,6 +58,21 @@ namespace ICD.Common.Utils.Extensions extends.WriteValue(name); } + /// + /// Gets the current value as a Type. + /// + /// + /// + [PublicAPI] + public static Type GetValueAsType(this JsonReader extends) + { + if (extends == null) + throw new ArgumentNullException("extends"); + + string value = extends.GetValueAsString(); + return Type.GetType(value, false, true); + } + /// /// Gets the current value as an integer. /// @@ -146,10 +161,36 @@ namespace ICD.Common.Utils.Extensions if (items == null) throw new ArgumentNullException("items"); + extends.SerializeArray(writer, items, (s, w, item) => s.Serialize(w, item)); + } + + /// + /// Serializes the given sequence of items to the writer. + /// + /// + /// + /// + /// + /// + public static void SerializeArray(this JsonSerializer extends, JsonWriter writer, IEnumerable items, + Action write) + { + if (extends == null) + throw new ArgumentNullException("extends"); + + if (writer == null) + throw new ArgumentNullException("writer"); + + if (items == null) + throw new ArgumentNullException("items"); + + if (write == null) + throw new ArgumentNullException("write"); + writer.WriteStartArray(); { foreach (TItem item in items) - extends.Serialize(writer, item); + write(extends, writer, item); } writer.WriteEndArray(); } @@ -168,6 +209,28 @@ namespace ICD.Common.Utils.Extensions if (reader == null) throw new ArgumentNullException("reader"); + return extends.DeserializeArray(reader, (s, r) => extends.Deserialize(reader)); + } + + /// + /// Deserializes an array of items from the reader's current value. + /// + /// + /// + /// + /// + public static IEnumerable DeserializeArray(this JsonSerializer extends, JsonReader reader, + Func read) + { + if (extends == null) + throw new ArgumentNullException("extends"); + + if (reader == null) + throw new ArgumentNullException("reader"); + + if (read == null) + throw new ArgumentNullException("read"); + if (reader.TokenType == JsonToken.Null) yield break; @@ -179,7 +242,7 @@ namespace ICD.Common.Utils.Extensions while (reader.TokenType != JsonToken.EndArray) { - TItem output = extends.Deserialize(reader); + TItem output = read(extends, reader); yield return output; // Read out of the last value From cd4791538a0928d690684bf7e8df3916926c9897 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Mon, 19 Feb 2018 15:23:08 -0500 Subject: [PATCH 10/12] Shim to instantiate a known type --- ICD.Common.Utils/ReflectionUtils.cs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/ICD.Common.Utils/ReflectionUtils.cs b/ICD.Common.Utils/ReflectionUtils.cs index 2cd7c36..76b182b 100644 --- a/ICD.Common.Utils/ReflectionUtils.cs +++ b/ICD.Common.Utils/ReflectionUtils.cs @@ -260,6 +260,21 @@ namespace ICD.Common.Utils } } + /// + /// Creates an instance of the given type, calling the default constructor. + /// + /// + public static T CreateInstance(Type type) + { + if (type == null) + throw new ArgumentNullException("type"); + + if (!type.IsAssignableTo(typeof(T))) + throw new InvalidOperationException("Type is not assignable to T"); + + return (T)CreateInstance(type); + } + /// /// Gets the custom attributes added to the given assembly. /// From 24d674337ba9b3e142bb2444c309a8fddd428cba Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Wed, 21 Feb 2018 12:17:57 -0500 Subject: [PATCH 11/12] Extension methods for finding distinct items based on a predicate --- .../Extensions/EnumerableExtensions.cs | 44 +++++++++++++++---- .../Extensions/PropertyEqualityComparer.cs | 41 +++++++++++++++++ ICD.Common.Utils/FuncComparer.cs | 36 --------------- .../ICD.Common.Utils_SimplSharp.csproj | 2 +- 4 files changed, 78 insertions(+), 45 deletions(-) create mode 100644 ICD.Common.Utils/Extensions/PropertyEqualityComparer.cs delete mode 100644 ICD.Common.Utils/FuncComparer.cs diff --git a/ICD.Common.Utils/Extensions/EnumerableExtensions.cs b/ICD.Common.Utils/Extensions/EnumerableExtensions.cs index f40fa3f..719d53c 100644 --- a/ICD.Common.Utils/Extensions/EnumerableExtensions.cs +++ b/ICD.Common.Utils/Extensions/EnumerableExtensions.cs @@ -653,23 +653,51 @@ namespace ICD.Common.Utils.Extensions } /// - /// Gets distinct elements from the sequence based on given callbacks. + /// Gets distinct elements from the sequence based on given property. /// - /// + /// + /// /// - /// - /// + /// /// [PublicAPI] - public static IEnumerable Distinct(this IEnumerable extends, Func comparer, Func getHashCode) + public static IEnumerable Distinct(this IEnumerable extends, + Func getProperty) { if (extends == null) throw new ArgumentNullException("extends"); - if (comparer == null) - throw new ArgumentNullException("comparer"); + if (getProperty == null) + throw new ArgumentNullException("getProperty"); - return extends.Distinct(new FuncComparer(comparer, getHashCode)); + IEqualityComparer comparer = EqualityComparer.Default; + return extends.Distinct(getProperty, comparer); + } + + /// + /// Gets distinct elements from the sequence based on given property. + /// + /// + /// + /// + /// + /// + /// + [PublicAPI] + public static IEnumerable Distinct(this IEnumerable extends, + Func getProperty, + IEqualityComparer propertyComparer) + { + if (extends == null) + throw new ArgumentNullException("extends"); + + if (getProperty == null) + throw new ArgumentNullException("getProperty"); + + if (propertyComparer == null) + throw new ArgumentNullException("propertyComparer"); + + return extends.Distinct(new PropertyEqualityComparer(propertyComparer, getProperty)); } /// diff --git a/ICD.Common.Utils/Extensions/PropertyEqualityComparer.cs b/ICD.Common.Utils/Extensions/PropertyEqualityComparer.cs new file mode 100644 index 0000000..57ef41a --- /dev/null +++ b/ICD.Common.Utils/Extensions/PropertyEqualityComparer.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; + +namespace ICD.Common.Utils.Extensions +{ + /// + /// Allows for comparing items based on some property. + /// + /// + /// + public sealed class PropertyEqualityComparer : IEqualityComparer + { + private readonly IEqualityComparer m_Comparer; + private readonly Func m_GetProperty; + + /// + /// Constructor. + /// + /// + /// + public PropertyEqualityComparer(IEqualityComparer comparer, Func getProperty) + { + m_Comparer = comparer; + m_GetProperty = getProperty; + } + + public bool Equals(TParent x, TParent y) + { + TProperty a = m_GetProperty(x); + TProperty b = m_GetProperty(y); + + return m_Comparer.Equals(a, b); + } + + public int GetHashCode(TParent parent) + { + TProperty property = m_GetProperty(parent); + return m_Comparer.GetHashCode(property); + } + } +} diff --git a/ICD.Common.Utils/FuncComparer.cs b/ICD.Common.Utils/FuncComparer.cs deleted file mode 100644 index 34b5894..0000000 --- a/ICD.Common.Utils/FuncComparer.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace ICD.Common.Utils -{ - /// - /// Simple comparer for comparing items using a callback. - /// - /// - public sealed class FuncComparer : IEqualityComparer - { - private readonly Func m_Comparer; - private readonly Func m_GetHashCode; - - /// - /// Constructor. - /// - /// - /// - public FuncComparer(Func comparer, Func getHashCode) - { - m_Comparer = comparer; - m_GetHashCode = getHashCode; - } - - public bool Equals(T x, T y) - { - return m_Comparer(x, y); - } - - public int GetHashCode(T obj) - { - return m_GetHashCode(obj); - } - } -} diff --git a/ICD.Common.Utils/ICD.Common.Utils_SimplSharp.csproj b/ICD.Common.Utils/ICD.Common.Utils_SimplSharp.csproj index 966b40e..665f60e 100644 --- a/ICD.Common.Utils/ICD.Common.Utils_SimplSharp.csproj +++ b/ICD.Common.Utils/ICD.Common.Utils_SimplSharp.csproj @@ -87,7 +87,7 @@ - + From 04d24c26c28377f20de073022d1ff78bbb4e58d4 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Wed, 21 Feb 2018 12:21:48 -0500 Subject: [PATCH 12/12] Additional enumerable extensions tests --- .../Extensions/EnumerableExtensionsTest.cs | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/ICD.Common.Utils.Tests/Extensions/EnumerableExtensionsTest.cs b/ICD.Common.Utils.Tests/Extensions/EnumerableExtensionsTest.cs index 70139af..13cdc40 100644 --- a/ICD.Common.Utils.Tests/Extensions/EnumerableExtensionsTest.cs +++ b/ICD.Common.Utils.Tests/Extensions/EnumerableExtensionsTest.cs @@ -374,6 +374,29 @@ namespace ICD.Common.Utils.Tests.Extensions Assert.AreEqual("C", values[2]); } + [Test] + public void DistinctTest() + { + string[] items = + { + "one", + "two", + "three" + }; + + items = items.Distinct(i => i.Length).ToArray(); + + Assert.AreEqual(2, items.Length); + Assert.AreEqual("one", items[0]); + Assert.AreEqual("three", items[1]); + } + + [Test] + public void DistinctComparerTest() + { + Assert.Inconclusive(); + } + [Test] public void UnanimousTest() {