diff --git a/src/SimplePatch.Tests/ConfigurationTests/Globals.cs b/src/SimplePatch.Tests/ConfigurationTests/Globals.cs index 83affe8..311ace1 100644 --- a/src/SimplePatch.Tests/ConfigurationTests/Globals.cs +++ b/src/SimplePatch.Tests/ConfigurationTests/Globals.cs @@ -1,4 +1,6 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; +using System.Collections.Generic; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Newtonsoft.Json.Linq; using SimplePatch.Mapping; using static SimplePatch.Tests.DeltaUtils; @@ -7,6 +9,13 @@ namespace SimplePatch.Tests.ConfigurationTests [TestClass, TestCategory(TestCategories.Configuration)] public class Globals : TestBase { + internal class Data + { + public string Category { get; set; } + + public Person PersonInfo { get; set; } + } + [TestCleanup] public void TestCleanup() { @@ -19,8 +28,8 @@ public void IgnoreLetterCase() DeltaConfig.Init(cfg => { cfg - .IgnoreLetterCase() - .AddEntity(); + .IgnoreLetterCase() + .AddEntity(); }); CreateDelta("AgE", 23).Patch(John); @@ -34,35 +43,35 @@ public void MappingFunction() { cfg - /* When the target property type is int and the input is string, - then the assigned value will be the length of the input string*/ - .AddMapping((propType, newValue) => - { - var result = new MapResult(); + /* When the target property type is int and the input is string, + then the assigned value will be the length of the input string*/ + .AddMapping((propType, newValue) => + { + var result = new MapResult(); - if (propType != typeof(int)) return result.SkipMap(); - if (newValue.GetType() != typeof(string)) return result.SkipMap(); + if (propType != typeof(int)) return result.SkipMap(); + if (newValue.GetType() != typeof(string)) return result.SkipMap(); - result.Value = newValue.ToString().Length; + result.Value = newValue.ToString().Length; - return result; - }) + return result; + }) - /* When the target property is double and the input is string, - then the assigned value will be the length of the string + 0.5*/ - .AddMapping((propType, newValue) => - { - var result = new MapResult(); + /* When the target property is double and the input is string, + then the assigned value will be the length of the string + 0.5*/ + .AddMapping((propType, newValue) => + { + var result = new MapResult(); - if (propType != typeof(double)) return result.SkipMap(); + if (propType != typeof(double)) return result.SkipMap(); - if (newValue.GetType() != typeof(string)) return result.SkipMap(); + if (newValue.GetType() != typeof(string)) return result.SkipMap(); - result.Value = newValue.ToString().Length + 0.5; + result.Value = newValue.ToString().Length + 0.5; - return result; - }) - .AddEntity(); + return result; + }) + .AddEntity(); }); // First mapping function will be executed here, Age type is int @@ -73,5 +82,39 @@ then the assigned value will be the length of the string + 0.5*/ CreateDelta(x => x.Height, "abcdef").Patch(John); Assert.AreEqual("abcdef".Length + 0.5, John.Height); } + + [TestMethod] + public void MappingToDeltaType() + { + DeltaConfig.Init(cfg => + { + cfg.AddEntity(); + cfg.AddEntity(); + cfg.AddMapping((propType, newValue) => + { + var result = new MapResult(); + if (!(newValue is JToken jToken)) return result.SkipMap(); + + var deltaOfEntity = (typeof(Delta<>)).MakeGenericType(propType); + result.Value = jToken.ToObject(deltaOfEntity); + return result; + }); + }); + + var data = new Data + { + Category = "Test", + PersonInfo = John + }; + + var dataDelta = new Delta + { + [nameof(Data.PersonInfo)] = JObject.FromObject(new Dictionary{[nameof(Person.Name)] = "Foo"}) + }; + + dataDelta.Patch(data); + Assert.AreEqual("Foo", data.PersonInfo.Name); + Assert.AreEqual("Doe", data.PersonInfo.Surname); + } } } diff --git a/src/SimplePatch.Tests/SimplePatch.Tests.csproj b/src/SimplePatch.Tests/SimplePatch.Tests.csproj index 320cf57..63180f7 100644 --- a/src/SimplePatch.Tests/SimplePatch.Tests.csproj +++ b/src/SimplePatch.Tests/SimplePatch.Tests.csproj @@ -44,6 +44,9 @@ ..\packages\MSTest.TestFramework.1.3.2\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll + + ..\packages\Newtonsoft.Json.12.0.2\lib\net45\Newtonsoft.Json.dll + diff --git a/src/SimplePatch.Tests/packages.config b/src/SimplePatch.Tests/packages.config index aa9eae9..0a01394 100644 --- a/src/SimplePatch.Tests/packages.config +++ b/src/SimplePatch.Tests/packages.config @@ -2,4 +2,5 @@ + \ No newline at end of file diff --git a/src/SimplePatch/Delta.cs b/src/SimplePatch/Delta.cs index c42ace0..83f39e3 100644 --- a/src/SimplePatch/Delta.cs +++ b/src/SimplePatch/Delta.cs @@ -229,10 +229,19 @@ private TEntity SetPropertiesValue(TEntity entity) if (!valueFromMappings.Skip) { - propertyInfo.SetValue(entity, valueFromMappings.Value); + var value = valueFromMappings.Value; + var valueType = value.GetType(); + if (valueType.GenericTypeArguments.Any() && valueType.GetGenericTypeDefinition() == typeof(Delta<>)) + { + valueType.GetMethod(nameof(Patch)).Invoke(value, new[] { propertyInfo.GetValue(entity, null) }); + } + else + { + propertyInfo.SetValue(entity, valueFromMappings.Value); + } } - // If no mapping function assigned a value to the property, use the default mapping - else + // If no mapping function assigned a value to the property, use the default mapping + else { var newPropertyValueType = newPropertyValue.GetType();