From 4f8a22594f4ee3dffcbb4a6e6cdbd8c064c86777 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Fri, 16 Sep 2016 16:10:13 +1200 Subject: [PATCH] -Added ISerializationBinder -Added SerializationBinder properties to JsonSerializer and JsonSerializerSettings -Changed Binder properties on JsonSerializer and JsonSerializerSettings to obsolete --- .../Bson/BsonReaderTests.cs | 2 + .../SerializeSerializationBinder.cs | 17 ++-- .../Serialization/JsonSerializerTest.cs | 32 ++++++ .../Serialization/TypeNameHandlingTests.cs | 97 +++++++++++++++++++ Src/Newtonsoft.Json/JsonSerializer.cs | 44 +++++++-- Src/Newtonsoft.Json/JsonSerializerSettings.cs | 27 +++++- .../Newtonsoft.Json.Net20.csproj | 2 + .../Newtonsoft.Json.Net35.csproj | 2 + .../Newtonsoft.Json.Net40.csproj | 2 + .../Newtonsoft.Json.Portable.csproj | 2 + .../Newtonsoft.Json.Portable40.csproj | 2 + Src/Newtonsoft.Json/Newtonsoft.Json.csproj | 2 + .../DefaultSerializationBinder.cs | 10 +- .../Serialization/ISerializationBinder.cs | 53 ++++++++++ .../JsonSerializerInternalReader.cs | 2 +- .../JsonSerializerInternalWriter.cs | 2 +- .../Serialization/JsonSerializerProxy.cs | 7 ++ .../SerializationBinderAdapter.cs | 55 +++++++++++ .../Utilities/ReflectionUtils.cs | 37 ++++--- 19 files changed, 358 insertions(+), 39 deletions(-) create mode 100644 Src/Newtonsoft.Json/Serialization/ISerializationBinder.cs create mode 100644 Src/Newtonsoft.Json/Serialization/SerializationBinderAdapter.cs diff --git a/Src/Newtonsoft.Json.Tests/Bson/BsonReaderTests.cs b/Src/Newtonsoft.Json.Tests/Bson/BsonReaderTests.cs index c5d80a66..f687d18c 100644 --- a/Src/Newtonsoft.Json.Tests/Bson/BsonReaderTests.cs +++ b/Src/Newtonsoft.Json.Tests/Bson/BsonReaderTests.cs @@ -1631,7 +1631,9 @@ namespace Newtonsoft.Json.Tests.Bson var settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto, +#pragma warning disable CS0618 // Type or member is obsolete Binder = binder +#pragma warning restore CS0618 // Type or member is obsolete }; Zoo zoo = new Zoo diff --git a/Src/Newtonsoft.Json.Tests/Documentation/Samples/Serializer/SerializeSerializationBinder.cs b/Src/Newtonsoft.Json.Tests/Documentation/Samples/Serializer/SerializeSerializationBinder.cs index 441d25a1..6a321414 100644 --- a/Src/Newtonsoft.Json.Tests/Documentation/Samples/Serializer/SerializeSerializationBinder.cs +++ b/Src/Newtonsoft.Json.Tests/Documentation/Samples/Serializer/SerializeSerializationBinder.cs @@ -23,10 +23,9 @@ // OTHER DEALINGS IN THE SOFTWARE. #endregion -#if !(NET20 || NET35) - using System; using System.Collections.Generic; +using Newtonsoft.Json.Serialization; using System.Runtime.Serialization; using System.Text; #if DNXCORE50 @@ -49,16 +48,16 @@ namespace Newtonsoft.Json.Tests.Documentation.Samples.Serializer public class SerializeSerializationBinder : TestFixtureBase { #region Types - public class KnownTypesBinder : SerializationBinder + public class KnownTypesBinder : ISerializationBinder { public IList KnownTypes { get; set; } - public override Type BindToType(string assemblyName, string typeName) + public Type BindToType(string assemblyName, string typeName) { return KnownTypes.SingleOrDefault(t => t.Name == typeName); } - public override void BindToName(Type serializedType, out string assemblyName, out string typeName) + public void BindToName(Type serializedType, out string assemblyName, out string typeName) { assemblyName = null; typeName = serializedType.Name; @@ -90,7 +89,7 @@ namespace Newtonsoft.Json.Tests.Documentation.Samples.Serializer string json = JsonConvert.SerializeObject(car, Formatting.Indented, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Objects, - Binder = knownTypesBinder + SerializationBinder = knownTypesBinder }); Console.WriteLine(json); @@ -103,7 +102,7 @@ namespace Newtonsoft.Json.Tests.Documentation.Samples.Serializer object newValue = JsonConvert.DeserializeObject(json, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Objects, - Binder = knownTypesBinder + SerializationBinder = knownTypesBinder }); Console.WriteLine(newValue.GetType().Name); @@ -113,6 +112,4 @@ namespace Newtonsoft.Json.Tests.Documentation.Samples.Serializer Assert.AreEqual("Car", newValue.GetType().Name); } } -} - -#endif \ No newline at end of file +} \ No newline at end of file diff --git a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs index 13c51028..34d24574 100644 --- a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs +++ b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs @@ -1178,8 +1178,23 @@ namespace Newtonsoft.Json.Tests.Serialization JsonSerializer serializer = new JsonSerializer(); DefaultSerializationBinder customBinder = new DefaultSerializationBinder(); +#pragma warning disable CS0618 // Type or member is obsolete serializer.Binder = customBinder; Assert.AreEqual(customBinder, serializer.Binder); +#pragma warning restore CS0618 // Type or member is obsolete + + Assert.IsInstanceOf(typeof(SerializationBinderAdapter), serializer.SerializationBinder); + + serializer.SerializationBinder = customBinder; + Assert.AreEqual(customBinder, serializer.SerializationBinder); + + ExceptionAssert.Throws(() => + { +#pragma warning disable CS0618 // Type or member is obsolete + var serializationBinder = serializer.Binder; +#pragma warning restore CS0618 // Type or member is obsolete + serializationBinder.ToString(); + }, "Cannot get SerializationBinder because an ISerializationBinder was previously set."); serializer.CheckAdditionalContent = true; Assert.AreEqual(true, serializer.CheckAdditionalContent); @@ -1273,8 +1288,10 @@ namespace Newtonsoft.Json.Tests.Serialization JsonSerializerSettings settings = new JsonSerializerSettings(); DefaultSerializationBinder customBinder = new DefaultSerializationBinder(); +#pragma warning disable CS0618 // Type or member is obsolete settings.Binder = customBinder; Assert.AreEqual(customBinder, settings.Binder); +#pragma warning restore CS0618 // Type or member is obsolete settings.CheckAdditionalContent = true; Assert.AreEqual(true, settings.CheckAdditionalContent); @@ -1374,8 +1391,23 @@ namespace Newtonsoft.Json.Tests.Serialization JsonSerializerProxy serializerProxy = new JsonSerializerProxy(new JsonSerializerInternalReader(new JsonSerializer())); DefaultSerializationBinder customBinder = new DefaultSerializationBinder(); +#pragma warning disable CS0618 // Type or member is obsolete serializerProxy.Binder = customBinder; Assert.AreEqual(customBinder, serializerProxy.Binder); +#pragma warning restore CS0618 // Type or member is obsolete + + Assert.IsInstanceOf(typeof(SerializationBinderAdapter), serializerProxy.SerializationBinder); + + serializerProxy.SerializationBinder = customBinder; + Assert.AreEqual(customBinder, serializerProxy.SerializationBinder); + + ExceptionAssert.Throws(() => + { +#pragma warning disable CS0618 // Type or member is obsolete + var serializationBinder = serializerProxy.Binder; +#pragma warning restore CS0618 // Type or member is obsolete + serializationBinder.ToString(); + }, "Cannot get SerializationBinder because an ISerializationBinder was previously set."); serializerProxy.CheckAdditionalContent = true; Assert.AreEqual(true, serializerProxy.CheckAdditionalContent); diff --git a/Src/Newtonsoft.Json.Tests/Serialization/TypeNameHandlingTests.cs b/Src/Newtonsoft.Json.Tests/Serialization/TypeNameHandlingTests.cs index fb901669..a7ede714 100644 --- a/Src/Newtonsoft.Json.Tests/Serialization/TypeNameHandlingTests.cs +++ b/Src/Newtonsoft.Json.Tests/Serialization/TypeNameHandlingTests.cs @@ -731,7 +731,9 @@ namespace Newtonsoft.Json.Tests.Serialization object p = JsonConvert.DeserializeObject(json, null, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Objects, +#pragma warning disable CS0618 // Type or member is obsolete Binder = new CustomSerializationBinder() +#pragma warning restore CS0618 // Type or member is obsolete }); CustomAssert.IsInstanceOfType(typeof(Person), p); @@ -772,7 +774,9 @@ namespace Newtonsoft.Json.Tests.Serialization string json = JsonConvert.SerializeObject(values, Formatting.Indented, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto, +#pragma warning disable CS0618 // Type or member is obsolete Binder = binder +#pragma warning restore CS0618 // Type or member is obsolete }); //[ @@ -804,7 +808,9 @@ namespace Newtonsoft.Json.Tests.Serialization IList newValues = JsonConvert.DeserializeObject>(json, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto, +#pragma warning disable CS0618 // Type or member is obsolete Binder = new TypeNameSerializationBinder("Newtonsoft.Json.Tests.Serialization.{0}, Newtonsoft.Json.Tests") +#pragma warning restore CS0618 // Type or member is obsolete }); CustomAssert.IsInstanceOfType(typeof(Customer), newValues[0]); @@ -840,6 +846,95 @@ namespace Newtonsoft.Json.Tests.Serialization } #endif + [Test] + public void NewSerializeUsingCustomBinder() + { + NewTypeNameSerializationBinder binder = new NewTypeNameSerializationBinder("Newtonsoft.Json.Tests.Serialization.{0}, Newtonsoft.Json.Tests"); + + IList values = new List + { + new Customer + { + Name = "Caroline Customer" + }, + new Purchase + { + ProductName = "Elbow Grease", + Price = 5.99m, + Quantity = 1 + } + }; + + string json = JsonConvert.SerializeObject(values, Formatting.Indented, new JsonSerializerSettings + { + TypeNameHandling = TypeNameHandling.Auto, + SerializationBinder = binder + }); + + //[ + // { + // "$type": "Customer", + // "Name": "Caroline Customer" + // }, + // { + // "$type": "Purchase", + // "ProductName": "Elbow Grease", + // "Price": 5.99, + // "Quantity": 1 + // } + //] + + StringAssert.AreEqual(@"[ + { + ""$type"": ""Customer"", + ""Name"": ""Caroline Customer"" + }, + { + ""$type"": ""Purchase"", + ""ProductName"": ""Elbow Grease"", + ""Price"": 5.99, + ""Quantity"": 1 + } +]", json); + + IList newValues = JsonConvert.DeserializeObject>(json, new JsonSerializerSettings + { + TypeNameHandling = TypeNameHandling.Auto, + SerializationBinder = new NewTypeNameSerializationBinder("Newtonsoft.Json.Tests.Serialization.{0}, Newtonsoft.Json.Tests") + }); + + CustomAssert.IsInstanceOfType(typeof(Customer), newValues[0]); + Customer customer = (Customer)newValues[0]; + Assert.AreEqual("Caroline Customer", customer.Name); + + CustomAssert.IsInstanceOfType(typeof(Purchase), newValues[1]); + Purchase purchase = (Purchase)newValues[1]; + Assert.AreEqual("Elbow Grease", purchase.ProductName); + } + + public class NewTypeNameSerializationBinder : ISerializationBinder + { + public string TypeFormat { get; private set; } + + public NewTypeNameSerializationBinder(string typeFormat) + { + TypeFormat = typeFormat; + } + + public void BindToName(Type serializedType, out string assemblyName, out string typeName) + { + assemblyName = null; + typeName = serializedType.Name; + } + + public Type BindToType(string assemblyName, string typeName) + { + string resolvedTypeName = string.Format(TypeFormat, typeName); + + return Type.GetType(resolvedTypeName, true); + } + } + [Test] public void CollectionWithAbstractItems() { @@ -1193,7 +1288,9 @@ namespace Newtonsoft.Json.Tests.Serialization { TypeNameHandling = TypeNameHandling.All, TypeNameAssemblyFormat = FormatterAssemblyStyle.Full, +#pragma warning disable CS0618 // Type or member is obsolete Binder = new MetroBinder(), +#pragma warning restore CS0618 // Type or member is obsolete ContractResolver = new DefaultContractResolver { #if !(NETFX_CORE || PORTABLE || DNXCORE50) diff --git a/Src/Newtonsoft.Json/JsonSerializer.cs b/Src/Newtonsoft.Json/JsonSerializer.cs index 75401162..7272dacb 100644 --- a/Src/Newtonsoft.Json/JsonSerializer.cs +++ b/Src/Newtonsoft.Json/JsonSerializer.cs @@ -58,7 +58,7 @@ namespace Newtonsoft.Json internal IContractResolver _contractResolver; internal ITraceWriter _traceWriter; internal IEqualityComparer _equalityComparer; - internal SerializationBinder _binder; + internal ISerializationBinder _serializationBinder; internal StreamingContext _context; private IReferenceResolver _referenceResolver; @@ -101,9 +101,24 @@ namespace Newtonsoft.Json /// /// Gets or sets the used by the serializer when resolving type names. /// + [Obsolete("Binder is obsolete. Use SerializationBinder instead.")] public virtual SerializationBinder Binder { - get { return _binder; } + get + { + if (_serializationBinder == null) + { + return null; + } + + SerializationBinderAdapter adapter = _serializationBinder as SerializationBinderAdapter; + if (adapter != null) + { + return adapter.SerializationBinder; + } + + throw new InvalidOperationException("Cannot get SerializationBinder because an ISerializationBinder was previously set."); + } set { if (value == null) @@ -111,7 +126,24 @@ namespace Newtonsoft.Json throw new ArgumentNullException(nameof(value), "Serialization binder cannot be null."); } - _binder = value; + _serializationBinder = new SerializationBinderAdapter(value); + } + } + + /// + /// Gets or sets the used by the serializer when resolving type names. + /// + public virtual ISerializationBinder SerializationBinder + { + get { return _serializationBinder; } + set + { + if (value == null) + { + throw new ArgumentNullException(nameof(value), "Serialization binder cannot be null."); + } + + _serializationBinder = value; } } @@ -488,7 +520,7 @@ namespace Newtonsoft.Json _typeNameHandling = JsonSerializerSettings.DefaultTypeNameHandling; _metadataPropertyHandling = JsonSerializerSettings.DefaultMetadataPropertyHandling; _context = JsonSerializerSettings.DefaultContext; - _binder = DefaultSerializationBinder.Instance; + _serializationBinder = DefaultSerializationBinder.Instance; _culture = JsonSerializerSettings.DefaultCulture; _contractResolver = DefaultContractResolver.Instance; @@ -656,9 +688,9 @@ namespace Newtonsoft.Json { serializer.EqualityComparer = settings.EqualityComparer; } - if (settings.Binder != null) + if (settings.SerializationBinder != null) { - serializer.Binder = settings.Binder; + serializer.SerializationBinder = settings.SerializationBinder; } // reader/writer specific diff --git a/Src/Newtonsoft.Json/JsonSerializerSettings.cs b/Src/Newtonsoft.Json/JsonSerializerSettings.cs index d3b9b49c..67d54d89 100644 --- a/Src/Newtonsoft.Json/JsonSerializerSettings.cs +++ b/Src/Newtonsoft.Json/JsonSerializerSettings.cs @@ -251,7 +251,32 @@ namespace Newtonsoft.Json /// Gets or sets the used by the serializer when resolving type names. /// /// The binder. - public SerializationBinder Binder { get; set; } + [Obsolete("Binder is obsolete. Use SerializationBinder instead.")] + public SerializationBinder Binder + { + get + { + if (SerializationBinder == null) + { + return null; + } + + SerializationBinderAdapter adapter = SerializationBinder as SerializationBinderAdapter; + if (adapter != null) + { + return adapter.SerializationBinder; + } + + throw new InvalidOperationException("Cannot get SerializationBinder because an ISerializationBinder was previously set."); + } + set { SerializationBinder = value == null ? null : new SerializationBinderAdapter(value); } + } + + /// + /// Gets or sets the used by the serializer when resolving type names. + /// + /// The binder. + public ISerializationBinder SerializationBinder { get; set; } /// /// Gets or sets the error handler called during serialization and deserialization. diff --git a/Src/Newtonsoft.Json/Newtonsoft.Json.Net20.csproj b/Src/Newtonsoft.Json/Newtonsoft.Json.Net20.csproj index 45c90c96..e9a38475 100644 --- a/Src/Newtonsoft.Json/Newtonsoft.Json.Net20.csproj +++ b/Src/Newtonsoft.Json/Newtonsoft.Json.Net20.csproj @@ -134,12 +134,14 @@ + + diff --git a/Src/Newtonsoft.Json/Newtonsoft.Json.Net35.csproj b/Src/Newtonsoft.Json/Newtonsoft.Json.Net35.csproj index 064c86a1..85dc6a80 100644 --- a/Src/Newtonsoft.Json/Newtonsoft.Json.Net35.csproj +++ b/Src/Newtonsoft.Json/Newtonsoft.Json.Net35.csproj @@ -148,11 +148,13 @@ + + diff --git a/Src/Newtonsoft.Json/Newtonsoft.Json.Net40.csproj b/Src/Newtonsoft.Json/Newtonsoft.Json.Net40.csproj index a80578fe..41ccf13e 100644 --- a/Src/Newtonsoft.Json/Newtonsoft.Json.Net40.csproj +++ b/Src/Newtonsoft.Json/Newtonsoft.Json.Net40.csproj @@ -147,11 +147,13 @@ + + diff --git a/Src/Newtonsoft.Json/Newtonsoft.Json.Portable.csproj b/Src/Newtonsoft.Json/Newtonsoft.Json.Portable.csproj index bf38c94e..044bb05d 100644 --- a/Src/Newtonsoft.Json/Newtonsoft.Json.Portable.csproj +++ b/Src/Newtonsoft.Json/Newtonsoft.Json.Portable.csproj @@ -179,6 +179,7 @@ + @@ -205,6 +206,7 @@ + diff --git a/Src/Newtonsoft.Json/Newtonsoft.Json.Portable40.csproj b/Src/Newtonsoft.Json/Newtonsoft.Json.Portable40.csproj index 3013712c..7b154cd3 100644 --- a/Src/Newtonsoft.Json/Newtonsoft.Json.Portable40.csproj +++ b/Src/Newtonsoft.Json/Newtonsoft.Json.Portable40.csproj @@ -184,6 +184,7 @@ + @@ -210,6 +211,7 @@ + diff --git a/Src/Newtonsoft.Json/Newtonsoft.Json.csproj b/Src/Newtonsoft.Json/Newtonsoft.Json.csproj index 31807f75..99b3dd05 100644 --- a/Src/Newtonsoft.Json/Newtonsoft.Json.csproj +++ b/Src/Newtonsoft.Json/Newtonsoft.Json.csproj @@ -169,6 +169,8 @@ + + diff --git a/Src/Newtonsoft.Json/Serialization/DefaultSerializationBinder.cs b/Src/Newtonsoft.Json/Serialization/DefaultSerializationBinder.cs index 102968a4..6d84e7d5 100644 --- a/Src/Newtonsoft.Json/Serialization/DefaultSerializationBinder.cs +++ b/Src/Newtonsoft.Json/Serialization/DefaultSerializationBinder.cs @@ -35,7 +35,7 @@ namespace Newtonsoft.Json.Serialization /// /// The default serialization binder used when resolving and loading classes from type names. /// - public class DefaultSerializationBinder : SerializationBinder + public class DefaultSerializationBinder : SerializationBinder, ISerializationBinder { internal static readonly DefaultSerializationBinder Instance = new DefaultSerializationBinder(); @@ -187,14 +187,17 @@ namespace Newtonsoft.Json.Serialization return GetTypeByName(new TypeNameKey(assemblyName, typeName)); } -#if !(NET35 || NET20) /// /// When overridden in a derived class, controls the binding of a serialized object to a type. /// /// The type of the object the formatter creates a new instance of. /// Specifies the name of the serialized object. /// Specifies the name of the serialized object. - public override void BindToName(Type serializedType, out string assemblyName, out string typeName) + public +#if !(NET35 || NET20) + override +#endif + void BindToName(Type serializedType, out string assemblyName, out string typeName) { #if (DOTNET || PORTABLE) assemblyName = serializedType.GetTypeInfo().Assembly.FullName; @@ -204,6 +207,5 @@ namespace Newtonsoft.Json.Serialization typeName = serializedType.FullName; #endif } -#endif } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json/Serialization/ISerializationBinder.cs b/Src/Newtonsoft.Json/Serialization/ISerializationBinder.cs new file mode 100644 index 00000000..bf70891b --- /dev/null +++ b/Src/Newtonsoft.Json/Serialization/ISerializationBinder.cs @@ -0,0 +1,53 @@ +#region License +// Copyright (c) 2007 James Newton-King +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +#endregion + +using System; +using System.Reflection; +using System.Runtime.Serialization; + +namespace Newtonsoft.Json.Serialization +{ + /// + /// Allows users to control class loading and mandate what class to load. + /// + public interface ISerializationBinder + { + /// + /// When implemented, controls the binding of a serialized object to a type. + /// + /// Specifies the name of the serialized object. + /// Specifies the name of the serialized object + /// The type of the object the formatter creates a new instance of. + Type BindToType(string assemblyName, string typeName); + + /// + /// When implemented, controls the binding of a serialized object to a type. + /// + /// The type of the object the formatter creates a new instance of. + /// Specifies the name of the serialized object. + /// Specifies the name of the serialized object. + void BindToName(Type serializedType, out string assemblyName, out string typeName); + } +} \ No newline at end of file diff --git a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs index 653810b3..91ca7233 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs @@ -783,7 +783,7 @@ namespace Newtonsoft.Json.Serialization Type specifiedType; try { - specifiedType = Serializer._binder.BindToType(typeNameKey.AssemblyName, typeNameKey.TypeName); + specifiedType = Serializer._serializationBinder.BindToType(typeNameKey.AssemblyName, typeNameKey.TypeName); } catch (Exception ex) { diff --git a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs index 6f2679e9..24b54ab6 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs @@ -603,7 +603,7 @@ namespace Newtonsoft.Json.Serialization private void WriteTypeProperty(JsonWriter writer, Type type) { - string typeName = ReflectionUtils.GetTypeName(type, Serializer._typeNameAssemblyFormat, Serializer._binder); + string typeName = ReflectionUtils.GetTypeName(type, Serializer._typeNameAssemblyFormat, Serializer._serializationBinder); if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) { diff --git a/Src/Newtonsoft.Json/Serialization/JsonSerializerProxy.cs b/Src/Newtonsoft.Json/Serialization/JsonSerializerProxy.cs index cd1c9101..036306e0 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonSerializerProxy.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonSerializerProxy.cs @@ -133,12 +133,19 @@ namespace Newtonsoft.Json.Serialization set { _serializer.ConstructorHandling = value; } } + [Obsolete("Binder is obsolete. Use SerializationBinder instead.")] public override SerializationBinder Binder { get { return _serializer.Binder; } set { _serializer.Binder = value; } } + public override ISerializationBinder SerializationBinder + { + get { return _serializer.SerializationBinder; } + set { _serializer.SerializationBinder = value; } + } + public override StreamingContext Context { get { return _serializer.Context; } diff --git a/Src/Newtonsoft.Json/Serialization/SerializationBinderAdapter.cs b/Src/Newtonsoft.Json/Serialization/SerializationBinderAdapter.cs new file mode 100644 index 00000000..bf171ff5 --- /dev/null +++ b/Src/Newtonsoft.Json/Serialization/SerializationBinderAdapter.cs @@ -0,0 +1,55 @@ +#region License +// Copyright (c) 2007 James Newton-King +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +#endregion + +using System; +using System.Runtime.Serialization; + +namespace Newtonsoft.Json.Serialization +{ + internal class SerializationBinderAdapter : ISerializationBinder + { + public readonly SerializationBinder SerializationBinder; + + public SerializationBinderAdapter(SerializationBinder serializationBinder) + { + SerializationBinder = serializationBinder; + } + + public Type BindToType(string assemblyName, string typeName) + { + return SerializationBinder.BindToType(assemblyName, typeName); + } + + public void BindToName(Type serializedType, out string assemblyName, out string typeName) + { +#if !(NET35 || NET20) + SerializationBinder.BindToName(serializedType, out assemblyName, out typeName); +#else + assemblyName = null; + typeName = null; +#endif + } + } +} \ No newline at end of file diff --git a/Src/Newtonsoft.Json/Utilities/ReflectionUtils.cs b/Src/Newtonsoft.Json/Utilities/ReflectionUtils.cs index a4b73df2..5c4e3baa 100644 --- a/Src/Newtonsoft.Json/Utilities/ReflectionUtils.cs +++ b/Src/Newtonsoft.Json/Utilities/ReflectionUtils.cs @@ -151,23 +151,9 @@ namespace Newtonsoft.Json.Utilities return (v != null) ? v.GetType() : null; } - public static string GetTypeName(Type t, FormatterAssemblyStyle assemblyFormat, SerializationBinder binder) + public static string GetTypeName(Type t, FormatterAssemblyStyle assemblyFormat, ISerializationBinder binder) { - string fullyQualifiedTypeName; -#if !(NET20 || NET35) - if (binder != null) - { - string assemblyName, typeName; - binder.BindToName(t, out assemblyName, out typeName); - fullyQualifiedTypeName = typeName + (assemblyName == null ? "" : ", " + assemblyName); - } - else - { - fullyQualifiedTypeName = t.AssemblyQualifiedName; - } -#else - fullyQualifiedTypeName = t.AssemblyQualifiedName; -#endif + string fullyQualifiedTypeName = GetFullyQualifiedTypeName(t, binder); switch (assemblyFormat) { @@ -180,6 +166,25 @@ namespace Newtonsoft.Json.Utilities } } + private static string GetFullyQualifiedTypeName(Type t, ISerializationBinder binder) + { + if (binder != null) + { + string assemblyName, typeName; + binder.BindToName(t, out assemblyName, out typeName); +#if (NET20 || NET35) + // for older SerializationBinder implementations that didn't have BindToName + if (assemblyName == null & typeName == null) + { + return t.AssemblyQualifiedName; + } +#endif + return typeName + (assemblyName == null ? "" : ", " + assemblyName); + } + + return t.AssemblyQualifiedName; + } + private static string RemoveAssemblyDetails(string fullyQualifiedTypeName) { StringBuilder builder = new StringBuilder();