From 3890d27d7f30ad9a39d871f82932c500bda74793 Mon Sep 17 00:00:00 2001 From: Tom Pipinic Date: Mon, 26 Dec 2022 10:14:23 +0100 Subject: [PATCH] Property aggregation bug fix --- .editorconfig | 4 +- src/Connected.Caching/SR.Designer.cs | 2 +- src/Connected.Collections/SR.Designer.cs | 2 +- src/Connected.Entities/SR.Designer.cs | 2 +- src/Connected.Hosting/SR.Designer.cs | 2 +- src/Connected.Interop/Merging/ObjectMerger.cs | 44 ++---------- .../Merging/PropertyAggregator.cs | 68 +++++++++++++++++++ .../Merging/PropertyResolver.cs | 19 ++++++ src/Connected.Interop/SR.Designer.cs | 2 +- src/Connected.Net/SR.Designer.cs | 2 +- src/Connected.Security/SR.Designer.cs | 2 +- src/Connected.Services/SR.Designer.cs | 2 +- src/Connected.Threading/SR.Designer.cs | 2 +- 13 files changed, 102 insertions(+), 51 deletions(-) create mode 100644 src/Connected.Interop/Merging/PropertyAggregator.cs create mode 100644 src/Connected.Interop/Merging/PropertyResolver.cs diff --git a/.editorconfig b/.editorconfig index fc2933b..8a11f4e 100644 --- a/.editorconfig +++ b/.editorconfig @@ -7,9 +7,9 @@ root = true #### Core EditorConfig Options #### # Indentation and spacing -indent_size = 4 +indent_size = 3 indent_style = tab -tab_width = 4 +tab_width = 3 # New line preferences end_of_line = crlf diff --git a/src/Connected.Caching/SR.Designer.cs b/src/Connected.Caching/SR.Designer.cs index cedd039..5b6fa9b 100644 --- a/src/Connected.Caching/SR.Designer.cs +++ b/src/Connected.Caching/SR.Designer.cs @@ -39,7 +39,7 @@ namespace Connected.Caching { internal static global::System.Resources.ResourceManager ResourceManager { get { if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Server.Caching.SR", typeof(SR).Assembly); + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Connected.Caching.SR", typeof(SR).Assembly); resourceMan = temp; } return resourceMan; diff --git a/src/Connected.Collections/SR.Designer.cs b/src/Connected.Collections/SR.Designer.cs index 0d04761..2503747 100644 --- a/src/Connected.Collections/SR.Designer.cs +++ b/src/Connected.Collections/SR.Designer.cs @@ -39,7 +39,7 @@ namespace Connected.Collections { internal static global::System.Resources.ResourceManager ResourceManager { get { if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Server.Collections.SR", typeof(SR).Assembly); + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Connected.Collections.SR", typeof(SR).Assembly); resourceMan = temp; } return resourceMan; diff --git a/src/Connected.Entities/SR.Designer.cs b/src/Connected.Entities/SR.Designer.cs index 5daecd2..0265690 100644 --- a/src/Connected.Entities/SR.Designer.cs +++ b/src/Connected.Entities/SR.Designer.cs @@ -39,7 +39,7 @@ namespace Connected.Entities { internal static global::System.Resources.ResourceManager ResourceManager { get { if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Server.Entities.SR", typeof(SR).Assembly); + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Connected.Entities.SR", typeof(SR).Assembly); resourceMan = temp; } return resourceMan; diff --git a/src/Connected.Hosting/SR.Designer.cs b/src/Connected.Hosting/SR.Designer.cs index 15ceb68..d6656c4 100644 --- a/src/Connected.Hosting/SR.Designer.cs +++ b/src/Connected.Hosting/SR.Designer.cs @@ -39,7 +39,7 @@ namespace Connected.Hosting { internal static global::System.Resources.ResourceManager ResourceManager { get { if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Server.Hosting.SR", typeof(SR).Assembly); + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Connected.Hosting.SR", typeof(SR).Assembly); resourceMan = temp; } return resourceMan; diff --git a/src/Connected.Interop/Merging/ObjectMerger.cs b/src/Connected.Interop/Merging/ObjectMerger.cs index c00017b..c5a58b7 100644 --- a/src/Connected.Interop/Merging/ObjectMerger.cs +++ b/src/Connected.Interop/Merging/ObjectMerger.cs @@ -1,5 +1,4 @@ -using Connected.ServiceModel; -using System.Collections; +using System.Collections; using System.Reflection; namespace Connected.Interop.Merging @@ -11,7 +10,7 @@ namespace Connected.Interop.Merging if (destination is null || !HasSource(sources)) return; - var sourceProperties = AggregateProperties(sources); + var sourceProperties = PropertyAggregator.Aggregate(sources); foreach (var property in Properties.GetImplementedProperties(destination)) MergeProperty(destination, sourceProperties, property); @@ -28,42 +27,6 @@ namespace Connected.Interop.Merging return false; } - private static Dictionary AggregateProperties(params object[] sources) - { - var result = new Dictionary(); - - for (var i = sources.Length - 1; i >= 0; i--) - { - var source = sources[i]; - - if (source is null) - continue; - - var props = Properties.GetImplementedProperties(source); - - foreach (var property in props) - { - if (result.ContainsKey(property.Name)) - continue; - - result.Add(property.Name, source); - } - - if (source is IPropertyProvider provider) - { - foreach (var property in provider.Properties) - { - if (result.ContainsKey(property.Key)) - continue; - - result.Add(property.Key, property.Value); - } - } - } - - return result; - } - private void MergeProperty(object destination, Dictionary sourceProperties, PropertyInfo property) { if (property.PropertyType.IsTypePrimitive()) @@ -74,7 +37,8 @@ namespace Connected.Interop.Merging if (!sourceProperties.TryGetValue(property.Name, out object? source)) return; - property.SetValue(destination, source.GetType().GetProperty(property.Name).GetValue(source)); + if (source.GetType() is Type propertyType && PropertyResolver.Resolve(propertyType, property.Name) is PropertyInfo propertyInfo) + property.SetValue(destination, propertyInfo.GetValue(source)); } else if (IsArray(property)) MergeEnumerable(destination, sourceProperties, property); diff --git a/src/Connected.Interop/Merging/PropertyAggregator.cs b/src/Connected.Interop/Merging/PropertyAggregator.cs new file mode 100644 index 0000000..052fbc2 --- /dev/null +++ b/src/Connected.Interop/Merging/PropertyAggregator.cs @@ -0,0 +1,68 @@ +using Connected.ServiceModel; + +namespace Connected.Interop.Merging; +internal static class PropertyAggregator +{ + public static Dictionary Aggregate(params object[] values) + { + var result = new Dictionary(StringComparer.OrdinalIgnoreCase); + + for (var i = values.Length - 1; i >= 0; i--) + { + if (values[i] is not object value) + continue; + + foreach (var property in GetImplementedProperties(value)) + { + if (result.ContainsKey(property.Key)) + continue; + + result.Add(property.Key, property.Value); + } + + if (value is IPropertyProvider provider) + { + foreach (var property in provider.Properties) + { + if (result.ContainsKey(property.Key)) + continue; + + result.Add(property.Key, property.Value); + } + } + } + + return result; + } + + private static Dictionary GetImplementedProperties(object value) + { + if (value is null) + return new(); + + if (value is object[] objectArray) + { + var result = new Dictionary(); + + for (var i = objectArray.Length - 1; i >= 0; i--) + { + var implementations = Properties.GetImplementedProperties(objectArray[i]); + + foreach (var property in implementations) + result.Add(property.Name, objectArray[i]); + } + + return result; + } + else + { + var implementations = Properties.GetImplementedProperties(value); + var result = new Dictionary(); + + foreach (var property in implementations) + result.Add(property.Name, value); + + return result; + } + } +} diff --git a/src/Connected.Interop/Merging/PropertyResolver.cs b/src/Connected.Interop/Merging/PropertyResolver.cs new file mode 100644 index 0000000..ba32fdc --- /dev/null +++ b/src/Connected.Interop/Merging/PropertyResolver.cs @@ -0,0 +1,19 @@ +using System.Reflection; + +namespace Connected.Interop.Merging; +internal static class PropertyResolver +{ + public static PropertyInfo? Resolve(Type type, string propertyName) + { + if (type.GetProperty(propertyName) is PropertyInfo property) + return property; + + if (type.GetProperty(propertyName.ToCamelCase()) is PropertyInfo camelProperty) + return camelProperty; + + if (type.GetProperty(propertyName.ToPascalCase()) is PropertyInfo pascalProperty) + return pascalProperty; + + return null; + } +} diff --git a/src/Connected.Interop/SR.Designer.cs b/src/Connected.Interop/SR.Designer.cs index 5d78d99..8c29b86 100644 --- a/src/Connected.Interop/SR.Designer.cs +++ b/src/Connected.Interop/SR.Designer.cs @@ -39,7 +39,7 @@ namespace Connected.Interop { internal static global::System.Resources.ResourceManager ResourceManager { get { if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Server.Interop.SR", typeof(SR).Assembly); + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Connected.Interop.SR", typeof(SR).Assembly); resourceMan = temp; } return resourceMan; diff --git a/src/Connected.Net/SR.Designer.cs b/src/Connected.Net/SR.Designer.cs index 0a5df82..7c56800 100644 --- a/src/Connected.Net/SR.Designer.cs +++ b/src/Connected.Net/SR.Designer.cs @@ -39,7 +39,7 @@ namespace Connected.Net { internal static global::System.Resources.ResourceManager ResourceManager { get { if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Server.Net.SR", typeof(SR).Assembly); + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Connected.Net.SR", typeof(SR).Assembly); resourceMan = temp; } return resourceMan; diff --git a/src/Connected.Security/SR.Designer.cs b/src/Connected.Security/SR.Designer.cs index 4c62e88..387c024 100644 --- a/src/Connected.Security/SR.Designer.cs +++ b/src/Connected.Security/SR.Designer.cs @@ -39,7 +39,7 @@ namespace Connected.Security { internal static global::System.Resources.ResourceManager ResourceManager { get { if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Server.Security.SR", typeof(SR).Assembly); + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Connected.Security.SR", typeof(SR).Assembly); resourceMan = temp; } return resourceMan; diff --git a/src/Connected.Services/SR.Designer.cs b/src/Connected.Services/SR.Designer.cs index 757bc43..ccc3baf 100644 --- a/src/Connected.Services/SR.Designer.cs +++ b/src/Connected.Services/SR.Designer.cs @@ -39,7 +39,7 @@ namespace Connected.Services { internal static global::System.Resources.ResourceManager ResourceManager { get { if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Server.Services.SR", typeof(SR).Assembly); + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Connected.Services.SR", typeof(SR).Assembly); resourceMan = temp; } return resourceMan; diff --git a/src/Connected.Threading/SR.Designer.cs b/src/Connected.Threading/SR.Designer.cs index 9a1d472..0399ab3 100644 --- a/src/Connected.Threading/SR.Designer.cs +++ b/src/Connected.Threading/SR.Designer.cs @@ -39,7 +39,7 @@ namespace Connected.Threading { internal static global::System.Resources.ResourceManager ResourceManager { get { if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Server.Threading.SR", typeof(SR).Assembly); + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Connected.Threading.SR", typeof(SR).Assembly); resourceMan = temp; } return resourceMan;