diff --git a/src/Microsoft.AspNetCore.JsonPatch/Adapters/AdapterFactory.cs b/src/Microsoft.AspNetCore.JsonPatch/Adapters/AdapterFactory.cs new file mode 100644 index 0000000000..c963fcffdd --- /dev/null +++ b/src/Microsoft.AspNetCore.JsonPatch/Adapters/AdapterFactory.cs @@ -0,0 +1,39 @@ +using Microsoft.AspNetCore.JsonPatch.Internal; +using Newtonsoft.Json.Serialization; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Text; + +namespace Microsoft.AspNetCore.JsonPatch.Adapters +{ + /// + /// The default AdapterFactory to be used for resolving . + /// + public class AdapterFactory : IAdapterFactory + { + /// + public virtual IAdapter Create(object target, IContractResolver contractResolver) + { + var jsonContract = contractResolver.ResolveContract(target.GetType()); + + if (target is IList) + { + return new ListAdapter(); + } + else if (jsonContract is JsonDictionaryContract jsonDictionaryContract) + { + var type = typeof(DictionaryAdapter<,>).MakeGenericType(jsonDictionaryContract.DictionaryKeyType, jsonDictionaryContract.DictionaryValueType); + return (IAdapter)Activator.CreateInstance(type); + } + else if (jsonContract is JsonDynamicContract) + { + return new DynamicObjectAdapter(); + } + else + { + return new PocoAdapter(); + } + } + } +} diff --git a/src/Microsoft.AspNetCore.JsonPatch/Adapters/IAdapterFactory.cs b/src/Microsoft.AspNetCore.JsonPatch/Adapters/IAdapterFactory.cs new file mode 100644 index 0000000000..43ca1e65b6 --- /dev/null +++ b/src/Microsoft.AspNetCore.JsonPatch/Adapters/IAdapterFactory.cs @@ -0,0 +1,22 @@ +using Microsoft.AspNetCore.JsonPatch.Internal; +using Newtonsoft.Json.Serialization; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Microsoft.AspNetCore.JsonPatch.Adapters +{ + /// + /// Defines the operations used for loading an based on the current object and ContractResolver. + /// + public interface IAdapterFactory + { + /// + /// Creates an for the current object + /// + /// The target object + /// The current contract resolver + /// The needed + IAdapter Create(object target, IContractResolver contractResolver); + } +} diff --git a/src/Microsoft.AspNetCore.JsonPatch/Adapters/ObjectAdapter.cs b/src/Microsoft.AspNetCore.JsonPatch/Adapters/ObjectAdapter.cs index 73095b52c2..48d7e69b0f 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Adapters/ObjectAdapter.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Adapters/ObjectAdapter.cs @@ -18,17 +18,37 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters /// The for logging . public ObjectAdapter( IContractResolver contractResolver, - Action logErrorAction) + Action logErrorAction): + this(contractResolver, logErrorAction, new AdapterFactory()) { - ContractResolver = contractResolver ?? throw new ArgumentNullException(nameof(contractResolver)); - LogErrorAction = logErrorAction; } + /// + /// Initializes a new instance of . + /// + /// The . + /// The for logging . + /// The to use when creating adaptors. + public ObjectAdapter( + IContractResolver contractResolver, + Action logErrorAction, + IAdapterFactory adapterFactory) + { + ContractResolver = contractResolver ?? throw new ArgumentNullException(nameof(contractResolver)); + LogErrorAction = logErrorAction; + AdapterFactory = adapterFactory ?? throw new ArgumentNullException(nameof(adapterFactory)); + } + /// /// Gets or sets the . /// public IContractResolver ContractResolver { get; } + /// + /// Gets or sets the + /// + public IAdapterFactory AdapterFactory { get; set; } + /// /// Action for logging . /// @@ -75,7 +95,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters } var parsedPath = new ParsedPath(path); - var visitor = new ObjectVisitor(parsedPath, ContractResolver); + var visitor = new ObjectVisitor(parsedPath, ContractResolver, AdapterFactory); var target = objectToApplyTo; if (!visitor.TryVisit(ref target, out var adapter, out var errorMessage)) @@ -144,7 +164,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters private void Remove(string path, object objectToApplyTo, Operation operationToReport) { var parsedPath = new ParsedPath(path); - var visitor = new ObjectVisitor(parsedPath, ContractResolver); + var visitor = new ObjectVisitor(parsedPath, ContractResolver, AdapterFactory); var target = objectToApplyTo; if (!visitor.TryVisit(ref target, out var adapter, out var errorMessage)) @@ -175,7 +195,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters } var parsedPath = new ParsedPath(operation.path); - var visitor = new ObjectVisitor(parsedPath, ContractResolver); + var visitor = new ObjectVisitor(parsedPath, ContractResolver, AdapterFactory); var target = objectToApplyTo; if (!visitor.TryVisit(ref target, out var adapter, out var errorMessage)) @@ -239,7 +259,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters } var parsedPath = new ParsedPath(operation.path); - var visitor = new ObjectVisitor(parsedPath, ContractResolver); + var visitor = new ObjectVisitor(parsedPath, ContractResolver, AdapterFactory); var target = objectToApplyTo; if (!visitor.TryVisit(ref target, out var adapter, out var errorMessage)) @@ -281,7 +301,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters propertyValue = null; var parsedPath = new ParsedPath(fromLocation); - var visitor = new ObjectVisitor(parsedPath, ContractResolver); + var visitor = new ObjectVisitor(parsedPath, ContractResolver, AdapterFactory); var target = objectToGetValueFrom; if (!visitor.TryVisit(ref target, out var adapter, out var errorMessage)) diff --git a/src/Microsoft.AspNetCore.JsonPatch/Internal/DictionaryAdapterOfTU.cs b/src/Microsoft.AspNetCore.JsonPatch/Internal/DictionaryAdapterOfTU.cs index 8a344e24ee..be2bbffd86 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Internal/DictionaryAdapterOfTU.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Internal/DictionaryAdapterOfTU.cs @@ -10,7 +10,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal { public class DictionaryAdapter : IAdapter { - public bool TryAdd( + public virtual bool TryAdd( object target, string segment, IContractResolver contractResolver, @@ -37,7 +37,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal return true; } - public bool TryGet( + public virtual bool TryGet( object target, string segment, IContractResolver contractResolver, @@ -66,7 +66,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal return true; } - public bool TryRemove( + public virtual bool TryRemove( object target, string segment, IContractResolver contractResolver, @@ -94,7 +94,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal return true; } - public bool TryReplace( + public virtual bool TryReplace( object target, string segment, IContractResolver contractResolver, @@ -128,7 +128,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal return true; } - public bool TryTest( + public virtual bool TryTest( object target, string segment, IContractResolver contractResolver, @@ -177,7 +177,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal } } - public bool TryTraverse( + public virtual bool TryTraverse( object target, string segment, IContractResolver contractResolver, @@ -208,7 +208,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal } } - private bool TryConvertKey(string key, out TKey convertedKey, out string errorMessage) + protected virtual bool TryConvertKey(string key, out TKey convertedKey, out string errorMessage) { var conversionResult = ConversionResultProvider.ConvertTo(key, typeof(TKey)); if (conversionResult.CanBeConverted) @@ -225,7 +225,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal } } - private bool TryConvertValue(object value, out TValue convertedValue, out string errorMessage) + protected virtual bool TryConvertValue(object value, out TValue convertedValue, out string errorMessage) { var conversionResult = ConversionResultProvider.ConvertTo(value, typeof(TValue)); if (conversionResult.CanBeConverted) diff --git a/src/Microsoft.AspNetCore.JsonPatch/Internal/DynamicObjectAdapter.cs b/src/Microsoft.AspNetCore.JsonPatch/Internal/DynamicObjectAdapter.cs index fb4adeb1f2..dc3c48266f 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Internal/DynamicObjectAdapter.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Internal/DynamicObjectAdapter.cs @@ -15,7 +15,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal { public class DynamicObjectAdapter : IAdapter { - public bool TryAdd( + public virtual bool TryAdd( object target, string segment, IContractResolver contractResolver, @@ -31,7 +31,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal return true; } - public bool TryGet( + public virtual bool TryGet( object target, string segment, IContractResolver contractResolver, @@ -48,7 +48,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal return true; } - public bool TryRemove( + public virtual bool TryRemove( object target, string segment, IContractResolver contractResolver, @@ -78,7 +78,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal } - public bool TryReplace( + public virtual bool TryReplace( object target, string segment, IContractResolver contractResolver, @@ -105,7 +105,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal return true; } - public bool TryTest( + public virtual bool TryTest( object target, string segment, IContractResolver contractResolver, @@ -135,7 +135,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal } } - public bool TryTraverse( + public virtual bool TryTraverse( object target, string segment, IContractResolver contractResolver, @@ -155,7 +155,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal } } - private bool TryGetDynamicObjectProperty( + protected virtual bool TryGetDynamicObjectProperty( object target, IContractResolver contractResolver, string segment, @@ -191,7 +191,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal } } - private bool TrySetDynamicObjectProperty( + protected virtual bool TrySetDynamicObjectProperty( object target, IContractResolver contractResolver, string segment, @@ -227,7 +227,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal } } - private bool TryConvertValue(object value, Type propertyType, out object convertedValue) + protected virtual bool TryConvertValue(object value, Type propertyType, out object convertedValue) { var conversionResult = ConversionResultProvider.ConvertTo(value, propertyType); if (!conversionResult.CanBeConverted) diff --git a/src/Microsoft.AspNetCore.JsonPatch/Internal/ListAdapter.cs b/src/Microsoft.AspNetCore.JsonPatch/Internal/ListAdapter.cs index d1348fd5c6..597f7b9f5f 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Internal/ListAdapter.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Internal/ListAdapter.cs @@ -13,7 +13,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal { public class ListAdapter : IAdapter { - public bool TryAdd( + public virtual bool TryAdd( object target, string segment, IContractResolver contractResolver, @@ -50,7 +50,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal return true; } - public bool TryGet( + public virtual bool TryGet( object target, string segment, IContractResolver contractResolver, @@ -84,7 +84,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal return true; } - public bool TryRemove( + public virtual bool TryRemove( object target, string segment, IContractResolver contractResolver, @@ -115,7 +115,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal return true; } - public bool TryReplace( + public virtual bool TryReplace( object target, string segment, IContractResolver contractResolver, @@ -152,7 +152,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal return true; } - public bool TryTest( + public virtual bool TryTest( object target, string segment, IContractResolver contractResolver, @@ -189,7 +189,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal } } - public bool TryTraverse( + public virtual bool TryTraverse( object target, string segment, IContractResolver contractResolver, @@ -224,7 +224,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal return true; } - private bool TryConvertValue( + protected virtual bool TryConvertValue( object originalValue, Type listTypeArgument, string segment, @@ -244,7 +244,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal return true; } - private bool TryGetListTypeArgument(IList list, out Type listTypeArgument, out string errorMessage) + protected virtual bool TryGetListTypeArgument(IList list, out Type listTypeArgument, out string errorMessage) { // Arrays are not supported as they have fixed size and operations like Add, Insert do not make sense var listType = list.GetType(); @@ -272,7 +272,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal } } - private bool TryGetPositionInfo( + protected virtual bool TryGetPositionInfo( IList list, string segment, OperationType operationType, @@ -318,7 +318,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal } } - private struct PositionInfo + protected struct PositionInfo { public PositionInfo(PositionType type, int index) { @@ -330,7 +330,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal public int Index { get; } } - private enum PositionType + protected enum PositionType { Index, // valid index EndOfList, // '-' @@ -338,7 +338,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal OutOfBounds } - private enum OperationType + protected enum OperationType { Add, Remove, diff --git a/src/Microsoft.AspNetCore.JsonPatch/Internal/ObjectVisitor.cs b/src/Microsoft.AspNetCore.JsonPatch/Internal/ObjectVisitor.cs index 8994f0aa52..a988afa300 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Internal/ObjectVisitor.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Internal/ObjectVisitor.cs @@ -3,19 +3,38 @@ using System; using System.Collections; +using Microsoft.AspNetCore.JsonPatch.Adapters; using Newtonsoft.Json.Serialization; namespace Microsoft.AspNetCore.JsonPatch.Internal { public class ObjectVisitor { + private readonly IAdapterFactory _adapterFactory; private readonly IContractResolver _contractResolver; private readonly ParsedPath _path; + /// + /// Initializes a new instance of . + /// + /// The path of the JsonPatch operation + /// The . public ObjectVisitor(ParsedPath path, IContractResolver contractResolver) + :this(path, contractResolver, new AdapterFactory()) { + } + + /// + /// Initializes a new instance of . + /// + /// The path of the JsonPatch operation + /// The . + /// The to use when creating adaptors. + public ObjectVisitor(ParsedPath path, IContractResolver contractResolver, IAdapterFactory adapterFactory) + { _path = path; _contractResolver = contractResolver ?? throw new ArgumentNullException(nameof(contractResolver)); + _adapterFactory = adapterFactory ?? throw new ArgumentNullException(nameof(adapterFactory)); } public bool TryVisit(ref object target, out IAdapter adapter, out string errorMessage) @@ -48,25 +67,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal private IAdapter SelectAdapter(object targetObject) { - var jsonContract = _contractResolver.ResolveContract(targetObject.GetType()); - - if (targetObject is IList) - { - return new ListAdapter(); - } - else if (jsonContract is JsonDictionaryContract jsonDictionaryContract) - { - var type = typeof(DictionaryAdapter<,>).MakeGenericType(jsonDictionaryContract.DictionaryKeyType, jsonDictionaryContract.DictionaryValueType); - return (IAdapter)Activator.CreateInstance(type); - } - else if (jsonContract is JsonDynamicContract) - { - return new DynamicObjectAdapter(); - } - else - { - return new PocoAdapter(); - } + return _adapterFactory.Create(targetObject, _contractResolver); } } } diff --git a/src/Microsoft.AspNetCore.JsonPatch/Internal/PocoAdapter.cs b/src/Microsoft.AspNetCore.JsonPatch/Internal/PocoAdapter.cs index 0eee0fc889..5ba3e5587b 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Internal/PocoAdapter.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Internal/PocoAdapter.cs @@ -12,7 +12,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal { public class PocoAdapter : IAdapter { - public bool TryAdd( + public virtual bool TryAdd( object target, string segment, IContractResolver contractResolver, @@ -43,7 +43,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal return true; } - public bool TryGet( + public virtual bool TryGet( object target, string segment, IContractResolver contractResolver, @@ -69,7 +69,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal return true; } - public bool TryRemove( + public virtual bool TryRemove( object target, string segment, IContractResolver contractResolver, @@ -102,7 +102,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal return true; } - public bool TryReplace( + public virtual bool TryReplace( object target, string segment, IContractResolver @@ -134,7 +134,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal return true; } - public bool TryTest( + public virtual bool TryTest( object target, string segment, IContractResolver @@ -171,7 +171,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal return true; } - public bool TryTraverse( + public virtual bool TryTraverse( object target, string segment, IContractResolver contractResolver, @@ -197,7 +197,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal return false; } - private bool TryGetJsonProperty( + protected virtual bool TryGetJsonProperty( object target, IContractResolver contractResolver, string segment, @@ -220,7 +220,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal return false; } - private bool TryConvertValue(object value, Type propertyType, out object convertedValue) + protected virtual bool TryConvertValue(object value, Type propertyType, out object convertedValue) { var conversionResult = ConversionResultProvider.ConvertTo(value, propertyType); if (!conversionResult.CanBeConverted) diff --git a/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocument.cs b/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocument.cs index b6539caae8..1888ea6b4b 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocument.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocument.cs @@ -174,7 +174,7 @@ namespace Microsoft.AspNetCore.JsonPatch throw new ArgumentNullException(nameof(objectToApplyTo)); } - ApplyTo(objectToApplyTo, new ObjectAdapter(ContractResolver, logErrorAction: null)); + ApplyTo(objectToApplyTo, new ObjectAdapter(ContractResolver, null, new AdapterFactory())); } /// @@ -183,13 +183,28 @@ namespace Microsoft.AspNetCore.JsonPatch /// Object to apply the JsonPatchDocument to /// Action to log errors public void ApplyTo(object objectToApplyTo, Action logErrorAction) + { + ApplyTo(objectToApplyTo, new ObjectAdapter(ContractResolver, logErrorAction, new AdapterFactory()), logErrorAction); + } + + /// + /// Apply this JsonPatchDocument + /// + /// Object to apply the JsonPatchDocument to + /// IObjectAdapter instance to use when applying + /// Action to log errors + public void ApplyTo(object objectToApplyTo, IObjectAdapter adapter, Action logErrorAction) { if (objectToApplyTo == null) { throw new ArgumentNullException(nameof(objectToApplyTo)); } - var adapter = new ObjectAdapter(ContractResolver, logErrorAction); + if (adapter == null) + { + throw new ArgumentNullException(nameof(adapter)); + } + foreach (var op in Operations) { try diff --git a/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocumentOfT.cs b/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocumentOfT.cs index 8ae1430185..3db0aac458 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocumentOfT.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocumentOfT.cs @@ -697,7 +697,7 @@ namespace Microsoft.AspNetCore.JsonPatch throw new ArgumentNullException(nameof(objectToApplyTo)); } - ApplyTo(objectToApplyTo, new ObjectAdapter(ContractResolver, logErrorAction: null)); + ApplyTo(objectToApplyTo, new ObjectAdapter(ContractResolver, null, new AdapterFactory())); } /// @@ -706,13 +706,28 @@ namespace Microsoft.AspNetCore.JsonPatch /// Object to apply the JsonPatchDocument to /// Action to log errors public void ApplyTo(TModel objectToApplyTo, Action logErrorAction) + { + ApplyTo(objectToApplyTo, new ObjectAdapter(ContractResolver, logErrorAction, new AdapterFactory()), logErrorAction); + } + + /// + /// Apply this JsonPatchDocument + /// + /// Object to apply the JsonPatchDocument to + /// IObjectAdapter instance to use when applying + /// Action to log errors + public void ApplyTo(TModel objectToApplyTo, IObjectAdapter adapter, Action logErrorAction) { if (objectToApplyTo == null) { throw new ArgumentNullException(nameof(objectToApplyTo)); } - var adapter = new ObjectAdapter(ContractResolver, logErrorAction); + if (adapter == null) + { + throw new ArgumentNullException(nameof(adapter)); + } + foreach (var op in Operations) { try diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Adapters/AdapterFactoryTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Adapters/AdapterFactoryTests.cs new file mode 100644 index 0000000000..1e961c29e9 --- /dev/null +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Adapters/AdapterFactoryTests.cs @@ -0,0 +1,73 @@ +using Microsoft.AspNetCore.JsonPatch.Adapters; +using Microsoft.AspNetCore.JsonPatch.Internal; +using Moq; +using Newtonsoft.Json.Serialization; +using System; +using System.Collections.Generic; +using System.Dynamic; +using System.Text; +using Xunit; + +namespace Microsoft.AspNetCore.JsonPatch.Test.Adapters +{ + public class AdapterFactoryTests + { + [Fact] + public void GetListAdapterForListTargets() + { + // Arrange + AdapterFactory factory = new AdapterFactory(); + + //Act: + IAdapter adapter = factory.Create(new List(), new DefaultContractResolver()); + + // Assert + Assert.Equal(typeof(ListAdapter), adapter.GetType()); + } + + [Fact] + public void GetDictionaryAdapterForDictionaryObjects() + { + // Arrange + AdapterFactory factory = new AdapterFactory(); + + //Act: + IAdapter adapter = factory.Create(new Dictionary(), new DefaultContractResolver()); + + // Assert + Assert.Equal(typeof(DictionaryAdapter), adapter.GetType()); + } + + private class PocoModel + {} + + + [Fact] + public void GetPocoAdapterForGenericObjects() + { + // Arrange + AdapterFactory factory = new AdapterFactory(); + + //Act: + IAdapter adapter = factory.Create(new PocoModel(), new DefaultContractResolver()); + + // Assert + Assert.Equal(typeof(PocoAdapter), adapter.GetType()); + } + + + + [Fact] + public void GetDynamicAdapterForGenericObjects() + { + // Arrange + AdapterFactory factory = new AdapterFactory(); + + //Act: + IAdapter adapter = factory.Create(new TestDynamicObject(), new DefaultContractResolver()); + + // Assert + Assert.Equal(typeof(DynamicObjectAdapter), adapter.GetType()); + } + } +} diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Adapters/TestDynamicObject.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Adapters/TestDynamicObject.cs new file mode 100644 index 0000000000..08371f25c6 --- /dev/null +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Adapters/TestDynamicObject.cs @@ -0,0 +1,10 @@ +using System; +using System.Collections.Generic; +using System.Dynamic; +using System.Text; + +namespace Microsoft.AspNetCore.JsonPatch.Test.Adapters +{ + public class TestDynamicObject : DynamicObject + { } +}