diff --git a/src/Microsoft.AspNetCore.JsonPatch/Adapters/AdapterFactory.cs b/src/Microsoft.AspNetCore.JsonPatch/Adapters/AdapterFactory.cs
new file mode 100644
index 0000000..9565bd3
--- /dev/null
+++ b/src/Microsoft.AspNetCore.JsonPatch/Adapters/AdapterFactory.cs
@@ -0,0 +1,39 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Text;
+using Microsoft.AspNetCore.JsonPatch.Internal;
+using Newtonsoft.Json.Serialization;
+
+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 0000000..43ca1e6
--- /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 73095b5..4e3783a 100644
--- a/src/Microsoft.AspNetCore.JsonPatch/Adapters/ObjectAdapter.cs
+++ b/src/Microsoft.AspNetCore.JsonPatch/Adapters/ObjectAdapter.cs
@@ -11,17 +11,31 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters
///
public class ObjectAdapter : IObjectAdapterWithTest
{
+ ///
+ /// Initializes a new instance of using the default AdapterFactory.
+ ///
+ /// The .
+ /// The for logging .
+ public ObjectAdapter(
+ IContractResolver contractResolver,
+ Action logErrorAction):this(contractResolver, logErrorAction, new AdapterFactory())
+ {
+ }
+
///
/// Initializes a new instance of .
///
/// The .
/// The for logging .
+ /// The to use when creating adaptors.
public ObjectAdapter(
IContractResolver contractResolver,
- Action logErrorAction)
+ Action logErrorAction,
+ IAdapterFactory adapterFactory)
{
ContractResolver = contractResolver ?? throw new ArgumentNullException(nameof(contractResolver));
LogErrorAction = logErrorAction;
+ AdapterFactory = adapterFactory;
}
///
@@ -29,6 +43,11 @@ public ObjectAdapter(
///
public IContractResolver ContractResolver { get; }
+ ///
+ /// Gets the
+ ///
+ public IAdapterFactory AdapterFactory { get; }
+
///
/// Action for logging .
///
@@ -75,7 +94,7 @@ private void Add(
}
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 +163,7 @@ public void Remove(Operation operation, object objectToApplyTo)
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 +194,7 @@ public void Replace(Operation operation, object objectToApplyTo)
}
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 +258,7 @@ public void Test(Operation operation, object objectToApplyTo)
}
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 +300,7 @@ private bool TryGetValue(
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/Converters/JsonPatchDocumentConverter.cs b/src/Microsoft.AspNetCore.JsonPatch/Converters/JsonPatchDocumentConverter.cs
index aed9c48..b5e3397 100644
--- a/src/Microsoft.AspNetCore.JsonPatch/Converters/JsonPatchDocumentConverter.cs
+++ b/src/Microsoft.AspNetCore.JsonPatch/Converters/JsonPatchDocumentConverter.cs
@@ -51,7 +51,7 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist
serializer.Populate(jObjectReader, targetOperations);
// container target: the JsonPatchDocument.
- var container = new JsonPatchDocument(targetOperations, new DefaultContractResolver());
+ var container = CreateContainer(targetOperations);
return container;
}
@@ -72,5 +72,14 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s
serializer.Serialize(writer, lst);
}
}
+
+ ///
+ /// Create the JsonPatchDocument using the appropriate constructor
+ ///
+ /// The operations to assign to the JsonPatchDocument
+ /// A new instance of the JsonPatchDocument
+ protected virtual JsonPatchDocument CreateContainer(List operations ) =>
+ new JsonPatchDocument(operations, new DefaultContractResolver());
+
}
}
diff --git a/src/Microsoft.AspNetCore.JsonPatch/Converters/TypedJsonPatchDocumentConverter.cs b/src/Microsoft.AspNetCore.JsonPatch/Converters/TypedJsonPatchDocumentConverter.cs
index fd779ba..b37cb90 100644
--- a/src/Microsoft.AspNetCore.JsonPatch/Converters/TypedJsonPatchDocumentConverter.cs
+++ b/src/Microsoft.AspNetCore.JsonPatch/Converters/TypedJsonPatchDocumentConverter.cs
@@ -51,7 +51,7 @@ public override object ReadJson(
serializer.Populate(jObjectReader, targetOperations);
// container target: the typed JsonPatchDocument.
- var container = Activator.CreateInstance(objectType, targetOperations, new DefaultContractResolver());
+ var container = CreateTypedContainer(objectType, targetOperations);
return container;
}
@@ -60,5 +60,16 @@ public override object ReadJson(
throw new JsonSerializationException(Resources.InvalidJsonPatchDocument, ex);
}
}
+
+ ///
+ /// Create the JsonPatchDocument using the appropriate constructor
+ ///
+ /// The model type for the JsonPatchDocument
+ /// The operations to assign to the JsonPatchDocument
+ /// A new instance of the JsonPatchDocument
+ protected virtual object CreateTypedContainer(Type objectType, object operations)
+ {
+ return Activator.CreateInstance(objectType, operations, new DefaultContractResolver());
+ }
}
}
\ No newline at end of file
diff --git a/src/Microsoft.AspNetCore.JsonPatch/Internal/DictionaryAdapterOfTU.cs b/src/Microsoft.AspNetCore.JsonPatch/Internal/DictionaryAdapterOfTU.cs
index 8a344e2..be2bbff 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 @@ public bool TryAdd(
return true;
}
- public bool TryGet(
+ public virtual bool TryGet(
object target,
string segment,
IContractResolver contractResolver,
@@ -66,7 +66,7 @@ public bool TryGet(
return true;
}
- public bool TryRemove(
+ public virtual bool TryRemove(
object target,
string segment,
IContractResolver contractResolver,
@@ -94,7 +94,7 @@ public bool TryRemove(
return true;
}
- public bool TryReplace(
+ public virtual bool TryReplace(
object target,
string segment,
IContractResolver contractResolver,
@@ -128,7 +128,7 @@ public bool TryReplace(
return true;
}
- public bool TryTest(
+ public virtual bool TryTest(
object target,
string segment,
IContractResolver contractResolver,
@@ -177,7 +177,7 @@ public bool TryTest(
}
}
- public bool TryTraverse(
+ public virtual bool TryTraverse(
object target,
string segment,
IContractResolver contractResolver,
@@ -208,7 +208,7 @@ public bool TryTraverse(
}
}
- 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 @@ private bool TryConvertKey(string key, out TKey convertedKey, out string errorMe
}
}
- 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 fb4adeb..dc3c482 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 @@ public bool TryAdd(
return true;
}
- public bool TryGet(
+ public virtual bool TryGet(
object target,
string segment,
IContractResolver contractResolver,
@@ -48,7 +48,7 @@ public bool TryGet(
return true;
}
- public bool TryRemove(
+ public virtual bool TryRemove(
object target,
string segment,
IContractResolver contractResolver,
@@ -78,7 +78,7 @@ public bool TryRemove(
}
- public bool TryReplace(
+ public virtual bool TryReplace(
object target,
string segment,
IContractResolver contractResolver,
@@ -105,7 +105,7 @@ public bool TryReplace(
return true;
}
- public bool TryTest(
+ public virtual bool TryTest(
object target,
string segment,
IContractResolver contractResolver,
@@ -135,7 +135,7 @@ public bool TryTest(
}
}
- public bool TryTraverse(
+ public virtual bool TryTraverse(
object target,
string segment,
IContractResolver contractResolver,
@@ -155,7 +155,7 @@ public bool TryTraverse(
}
}
- private bool TryGetDynamicObjectProperty(
+ protected virtual bool TryGetDynamicObjectProperty(
object target,
IContractResolver contractResolver,
string segment,
@@ -191,7 +191,7 @@ private bool TryGetDynamicObjectProperty(
}
}
- private bool TrySetDynamicObjectProperty(
+ protected virtual bool TrySetDynamicObjectProperty(
object target,
IContractResolver contractResolver,
string segment,
@@ -227,7 +227,7 @@ private bool TrySetDynamicObjectProperty(
}
}
- 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 d1348fd..597f7b9 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 @@ public bool TryAdd(
return true;
}
- public bool TryGet(
+ public virtual bool TryGet(
object target,
string segment,
IContractResolver contractResolver,
@@ -84,7 +84,7 @@ public bool TryGet(
return true;
}
- public bool TryRemove(
+ public virtual bool TryRemove(
object target,
string segment,
IContractResolver contractResolver,
@@ -115,7 +115,7 @@ public bool TryRemove(
return true;
}
- public bool TryReplace(
+ public virtual bool TryReplace(
object target,
string segment,
IContractResolver contractResolver,
@@ -152,7 +152,7 @@ public bool TryReplace(
return true;
}
- public bool TryTest(
+ public virtual bool TryTest(
object target,
string segment,
IContractResolver contractResolver,
@@ -189,7 +189,7 @@ public bool TryTest(
}
}
- public bool TryTraverse(
+ public virtual bool TryTraverse(
object target,
string segment,
IContractResolver contractResolver,
@@ -224,7 +224,7 @@ public bool TryTraverse(
return true;
}
- private bool TryConvertValue(
+ protected virtual bool TryConvertValue(
object originalValue,
Type listTypeArgument,
string segment,
@@ -244,7 +244,7 @@ private bool TryConvertValue(
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 @@ private bool TryGetListTypeArgument(IList list, out Type listTypeArgument, out s
}
}
- private bool TryGetPositionInfo(
+ protected virtual bool TryGetPositionInfo(
IList list,
string segment,
OperationType operationType,
@@ -318,7 +318,7 @@ private bool TryGetPositionInfo(
}
}
- private struct PositionInfo
+ protected struct PositionInfo
{
public PositionInfo(PositionType type, int index)
{
@@ -330,7 +330,7 @@ public PositionInfo(PositionType type, int index)
public int Index { get; }
}
- private enum PositionType
+ protected enum PositionType
{
Index, // valid index
EndOfList, // '-'
@@ -338,7 +338,7 @@ private enum PositionType
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 8994f0a..297a8b4 100644
--- a/src/Microsoft.AspNetCore.JsonPatch/Internal/ObjectVisitor.cs
+++ b/src/Microsoft.AspNetCore.JsonPatch/Internal/ObjectVisitor.cs
@@ -3,19 +3,37 @@
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;
- public ObjectVisitor(ParsedPath path, IContractResolver contractResolver)
+ ///
+ /// Initializes a new instance of using the default .
+ ///
+ /// 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;
}
public bool TryVisit(ref object target, out IAdapter adapter, out string errorMessage)
@@ -48,25 +66,7 @@ public bool TryVisit(ref object target, out IAdapter adapter, out string errorMe
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 0eee0fc..5ba3e55 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 @@ public bool TryAdd(
return true;
}
- public bool TryGet(
+ public virtual bool TryGet(
object target,
string segment,
IContractResolver contractResolver,
@@ -69,7 +69,7 @@ public bool TryGet(
return true;
}
- public bool TryRemove(
+ public virtual bool TryRemove(
object target,
string segment,
IContractResolver contractResolver,
@@ -102,7 +102,7 @@ public bool TryRemove(
return true;
}
- public bool TryReplace(
+ public virtual bool TryReplace(
object target,
string segment,
IContractResolver
@@ -134,7 +134,7 @@ public bool TryReplace(
return true;
}
- public bool TryTest(
+ public virtual bool TryTest(
object target,
string segment,
IContractResolver
@@ -171,7 +171,7 @@ public bool TryTest(
return true;
}
- public bool TryTraverse(
+ public virtual bool TryTraverse(
object target,
string segment,
IContractResolver contractResolver,
@@ -197,7 +197,7 @@ public bool TryTraverse(
return false;
}
- private bool TryGetJsonProperty(
+ protected virtual bool TryGetJsonProperty(
object target,
IContractResolver contractResolver,
string segment,
@@ -220,7 +220,7 @@ private bool TryGetJsonProperty(
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 4420e57..094ff35 100644
--- a/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocument.cs
+++ b/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocument.cs
@@ -24,26 +24,25 @@ public class JsonPatchDocument : IJsonPatchDocument
[JsonIgnore]
public IContractResolver ContractResolver { get; set; }
- public JsonPatchDocument()
+ ///
+ /// Gets or sets the AdapterFactory to use when processing this document
+ ///
+ [JsonIgnore]
+ public IAdapterFactory AdapterFactory { get; set; }
+
+ public JsonPatchDocument():this(new List(), new DefaultContractResolver())
{
- Operations = new List();
- ContractResolver = new DefaultContractResolver();
}
- public JsonPatchDocument(List operations, IContractResolver contractResolver)
+ public JsonPatchDocument(List operations, IContractResolver contractResolver):this(operations, contractResolver, new AdapterFactory())
{
- if (operations == null)
- {
- throw new ArgumentNullException(nameof(operations));
- }
-
- if (contractResolver == null)
- {
- throw new ArgumentNullException(nameof(contractResolver));
- }
+ }
- Operations = operations;
- ContractResolver = contractResolver;
+ public JsonPatchDocument(List operations, IContractResolver contractResolver, IAdapterFactory adapterFactory)
+ {
+ Operations = operations ?? throw new ArgumentNullException(nameof(operations));
+ ContractResolver = contractResolver ?? throw new ArgumentNullException(nameof(contractResolver));
+ AdapterFactory = adapterFactory ?? throw new ArgumentNullException(nameof(adapterFactory));
}
///
@@ -174,7 +173,7 @@ public void ApplyTo(object objectToApplyTo)
throw new ArgumentNullException(nameof(objectToApplyTo));
}
- ApplyTo(objectToApplyTo, new ObjectAdapter(ContractResolver, logErrorAction: null));
+ ApplyTo(objectToApplyTo, new ObjectAdapter(ContractResolver, null, AdapterFactory));
}
///
@@ -189,7 +188,7 @@ public void ApplyTo(object objectToApplyTo, Action logErrorActio
throw new ArgumentNullException(nameof(objectToApplyTo));
}
- var adapter = new ObjectAdapter(ContractResolver, logErrorAction);
+ var adapter = new ObjectAdapter(ContractResolver, logErrorAction, AdapterFactory);
foreach (var op in Operations)
{
try
diff --git a/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocumentOfT.cs b/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocumentOfT.cs
index 8ae1430..c5c5b19 100644
--- a/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocumentOfT.cs
+++ b/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocumentOfT.cs
@@ -28,17 +28,25 @@ public class JsonPatchDocument : IJsonPatchDocument where TModel : class
[JsonIgnore]
public IContractResolver ContractResolver { get; set; }
- public JsonPatchDocument()
+ ///
+ /// Gets or sets the AdapterFactory to use when processing this document
+ ///
+ [JsonIgnore]
+ public IAdapterFactory AdapterFactory { get; set; }
+
+ public JsonPatchDocument() : this(new List>(), new DefaultContractResolver())
+ {
+ }
+
+ public JsonPatchDocument(List> operations, IContractResolver contractResolver) : this(operations, contractResolver, new AdapterFactory())
{
- Operations = new List>();
- ContractResolver = new DefaultContractResolver();
}
- // Create from list of operations
- public JsonPatchDocument(List> operations, IContractResolver contractResolver)
+ public JsonPatchDocument(List> operations, IContractResolver contractResolver, IAdapterFactory adapterFactory)
{
Operations = operations ?? throw new ArgumentNullException(nameof(operations));
ContractResolver = contractResolver ?? throw new ArgumentNullException(nameof(contractResolver));
+ AdapterFactory = adapterFactory ?? throw new ArgumentNullException(nameof(adapterFactory));
}
///
@@ -697,7 +705,7 @@ public void ApplyTo(TModel objectToApplyTo)
throw new ArgumentNullException(nameof(objectToApplyTo));
}
- ApplyTo(objectToApplyTo, new ObjectAdapter(ContractResolver, logErrorAction: null));
+ ApplyTo(objectToApplyTo, new ObjectAdapter(ContractResolver, null, AdapterFactory));
}
///
@@ -712,7 +720,7 @@ public void ApplyTo(TModel objectToApplyTo, Action logErrorActio
throw new ArgumentNullException(nameof(objectToApplyTo));
}
- var adapter = new ObjectAdapter(ContractResolver, logErrorAction);
+ var adapter = new ObjectAdapter(ContractResolver, logErrorAction, AdapterFactory);
foreach (var op in Operations)
{
try
diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentTest.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentTest.cs
index 197e514..1da12fc 100644
--- a/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentTest.cs
+++ b/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentTest.cs
@@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.JsonPatch.Exceptions;
+using Microsoft.AspNetCore.JsonPatch.Test;
using Newtonsoft.Json;
using Xunit;
@@ -158,5 +159,30 @@ var deserialized
// Assert
Assert.Equal("The JSON patch document was malformed and could not be parsed.", exception.Message);
}
+
+ [Fact]
+ public void Deserialization_Supports_Custom_AdapterFactory()
+ {
+ // Arrange
+ var doc = new SimpleObject()
+ {
+ StringProperty = "A",
+ DecimalValue = 10,
+ DoubleValue = 10,
+ FloatValue = 10,
+ IntegerValue = 10
+ };
+
+ var patchDocument = new JsonPatchDocument();
+
+ var serialized = JsonConvert.SerializeObject(patchDocument);
+ JsonSerializerSettings serializerSettings = new JsonSerializerSettings();
+ serializerSettings.ContractResolver = new JsonPatchDocumentResolverForCustomFactory();
+
+ JsonPatchDocument deserialized = JsonConvert.DeserializeObject>(serialized, serializerSettings);
+
+ // Assert
+ Assert.Equal(typeof(TestAdapterFactory) ,deserialized.AdapterFactory.GetType());
+ }
}
}
diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/TestAdapterFactory.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/TestAdapterFactory.cs
new file mode 100644
index 0000000..a88bf2c
--- /dev/null
+++ b/test/Microsoft.AspNetCore.JsonPatch.Test/TestAdapterFactory.cs
@@ -0,0 +1,80 @@
+using Microsoft.AspNetCore.JsonPatch.Adapters;
+using Microsoft.AspNetCore.JsonPatch.Converters;
+using Microsoft.AspNetCore.JsonPatch.Internal;
+using Microsoft.AspNetCore.JsonPatch.Operations;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Serialization;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Microsoft.AspNetCore.JsonPatch.Test
+{
+ public class TestAdapterFactory : IAdapterFactory
+ {
+ public IAdapter Create(object target, IContractResolver contractResolver)
+ {
+ return new TestAdapter(target, contractResolver);
+ }
+ }
+
+ public class TestAdapter : IAdapter
+ {
+ public Object Target { get; }
+ public IContractResolver ContractResolver { get; }
+ public TestAdapter(object target, IContractResolver contractResolver)
+ {
+ Target = target;
+ ContractResolver = contractResolver;
+ }
+ public bool TryAdd(object target, string segment, IContractResolver contractResolver, object value, out string errorMessage)
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool TryGet(object target, string segment, IContractResolver contractResolver, out object value, out string errorMessage)
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool TryRemove(object target, string segment, IContractResolver contractResolver, out string errorMessage)
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool TryReplace(object target, string segment, IContractResolver contractResolver, object value, out string errorMessage)
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool TryTest(object target, string segment, IContractResolver contractResolver, object value, out string errorMessage)
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool TryTraverse(object target, string segment, IContractResolver contractResolver, out object nextTarget, out string errorMessage)
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ public class JsonPatchDocumentResolverForCustomFactory:DefaultContractResolver
+ {
+ protected override JsonConverter ResolveContractConverter(Type objectType)
+ {
+ return new JsonPatchDocumentConverterWithCustomFactory();
+ }
+ }
+
+ public class JsonPatchDocumentConverterWithCustomFactory: TypedJsonPatchDocumentConverter
+ {
+ public JsonPatchDocumentConverterWithCustomFactory()
+ {
+ }
+
+ protected override object CreateTypedContainer(Type objectType, object operations)
+ {
+ return Activator.CreateInstance(objectType, operations, new DefaultContractResolver(), new TestAdapterFactory());
+ }
+ }
+}