-Added JsonConstructorAttribute to explicitly define which constructor to use during deserialization

-Added IFormattable to JValue
-Changed JValue ToString to call ToString on the internal value
-Fixed code emit error when deserializing interfaces in certain situations
This commit is contained in:
JamesNK
2011-01-15 00:44:26 +00:00
parent 5d062cc8f8
commit 3535173716
18 changed files with 347 additions and 32 deletions
@@ -7,6 +7,7 @@ using System.Text;
using Newtonsoft.Json.Linq;
using NUnit.Framework;
using Newtonsoft.Json.Utilities;
using System.Globalization;
namespace Newtonsoft.Json.Tests.Linq
{
@@ -106,6 +107,56 @@ namespace Newtonsoft.Json.Tests.Linq
Assert.AreEqual("blah blah", (string)v);
}
//[Test]
//public void JValueEquals()
//{
// JObject o = new JObject(
// new JProperty("Null", new JValue(null, JTokenType.Null)),
// new JProperty("Integer", new JValue(1)),
// new JProperty("Float", new JValue(1.1)),
// new JProperty("DateTime", new JValue(new DateTime(2000, 12, 29, 23, 51, 10, DateTimeKind.Utc))),
// new JProperty("Boolean", new JValue(true)),
// new JProperty("String", new JValue("A string lol!")),
// new JProperty("Bytes", new JValue(Encoding.UTF8.GetBytes("A string lol!")))
// );
// dynamic d = o;
// Assert.IsTrue(d.Null == null);
// Assert.IsTrue(d.Null == new JValue(null, JTokenType.Null));
// //if (d.NullValue == null)
// // Console.WriteLine("Null");
// //else
// // Console.WriteLine("Not null");
// //Console.WriteLine(d.IntValue == 1);
//}
[Test]
public void JValueToString()
{
JObject o = new JObject(
new JProperty("Null", new JValue(null, JTokenType.Null)),
new JProperty("Integer", new JValue(1)),
new JProperty("Float", new JValue(1.1)),
new JProperty("DateTime", new JValue(new DateTime(2000, 12, 29, 23, 51, 10, DateTimeKind.Utc))),
new JProperty("Boolean", new JValue(true)),
new JProperty("String", new JValue("A string lol!")),
new JProperty("Bytes", new JValue(Encoding.UTF8.GetBytes("A string lol!")))
);
dynamic d = o;
Assert.AreEqual("", d.Null.ToString());
Assert.AreEqual("1", d.Integer.ToString());
Assert.AreEqual("1.1", d.Float.ToString());
Assert.AreEqual("12/29/2000 23:51:10", d.DateTime.ToString(null, CultureInfo.InvariantCulture));
Assert.AreEqual("True", d.Boolean.ToString());
Assert.AreEqual("A string lol!", d.String.ToString());
Assert.AreEqual("System.Byte[]", d.Bytes.ToString());
}
[Test]
public void JObjectGetDynamicPropertyNames()
{
@@ -29,6 +29,7 @@ using System.Linq;
using System.Text;
using NUnit.Framework;
using Newtonsoft.Json.Linq;
using System.Globalization;
namespace Newtonsoft.Json.Tests.Linq
{
@@ -92,6 +93,30 @@ namespace Newtonsoft.Json.Tests.Linq
Assert.AreEqual(JTokenType.String, stringValue.Type);
}
[Test]
public void ToString()
{
JValue v;
v = new JValue(true);
Assert.AreEqual("True", v.ToString());
v = new JValue(Encoding.UTF8.GetBytes("Blah"));
Assert.AreEqual("System.Byte[]", v.ToString(null, CultureInfo.InvariantCulture));
v = new JValue("I am a string!");
Assert.AreEqual("I am a string!", v.ToString());
v = new JValue(null, JTokenType.Null);
Assert.AreEqual("", v.ToString());
v = new JValue(null, JTokenType.Null);
Assert.AreEqual("", v.ToString(null, CultureInfo.InvariantCulture));
v = new JValue(new DateTime(2000, 12, 12, 20, 59, 59, DateTimeKind.Utc), JTokenType.Date);
Assert.AreEqual("12/12/2000 20:59:59", v.ToString(null, CultureInfo.InvariantCulture));
}
[Test]
[ExpectedException(typeof(InvalidOperationException), ExpectedMessage = "Cannot access child value on Newtonsoft.Json.Linq.JValue.")]
public void Last()
@@ -287,7 +287,7 @@ keyword such as type of business.""
Assert.AreEqual(@"""Width"": 1.1", o.Property("Width").ToString());
Assert.AreEqual(@"1.1", o.Property("Width").Value.ToString());
Assert.AreEqual(@"""Open"": false", o.Property("Open").ToString());
Assert.AreEqual(@"false", o.Property("Open").Value.ToString());
Assert.AreEqual(@"False", o.Property("Open").Value.ToString());
json = @"[null,undefined]";
@@ -296,8 +296,8 @@ keyword such as type of business.""
null,
undefined
]", a.ToString());
Assert.AreEqual(@"null", a.Children().ElementAt(0).ToString());
Assert.AreEqual(@"undefined", a.Children().ElementAt(1).ToString());
Assert.AreEqual(@"", a.Children().ElementAt(0).ToString());
Assert.AreEqual(@"", a.Children().ElementAt(1).ToString());
}
[Test]
@@ -10,7 +10,7 @@ namespace Newtonsoft.Json.Tests.Serialization
public class ConstructorHandlingTests : TestFixtureBase
{
[Test]
[ExpectedException(typeof(JsonSerializationException), ExpectedMessage = "Unable to find a constructor to use for type Newtonsoft.Json.Tests.TestObjects.PrivateConstructorTestClass. A class should either have a default constructor or only one constructor with arguments.")]
[ExpectedException(typeof(JsonSerializationException), ExpectedMessage = "Unable to find a constructor to use for type Newtonsoft.Json.Tests.TestObjects.PrivateConstructorTestClass. A class should either have a default constructor, one constructor with arguments or a constructor marked with the JsonConstructor attribute.")]
public void FailWithPrivateConstructorAndDefault()
{
string json = @"{Name:""Name!""}";
@@ -39,8 +39,58 @@ namespace Newtonsoft.Json.Tests.Serialization
public string AuthorCountry { get; set; }
}
public interface IPerson
{
string FirstName { get; set; }
string LastName { get; set; }
DateTime BirthDate { get; set; }
}
public class Employee : IPerson
{
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime BirthDate { get; set; }
public string Department { get; set; }
public string JobTitle { get; set; }
}
public class IPersonContractResolver : DefaultContractResolver
{
protected override JsonContract CreateContract(Type objectType)
{
if (objectType == typeof(Employee))
objectType = typeof(IPerson);
return base.CreateContract(objectType);
}
}
public class ContractResolverTests : TestFixtureBase
{
[Test]
public void SerializeInterface()
{
Employee employee = new Employee
{
BirthDate = new DateTime(1977, 12, 30, 1, 1, 1, DateTimeKind.Utc),
FirstName = "Maurice",
LastName = "Moss",
Department = "IT",
JobTitle = "Support"
};
string iPersonJson = JsonConvert.SerializeObject(employee, Formatting.Indented,
new JsonSerializerSettings { ContractResolver = new IPersonContractResolver() });
Assert.AreEqual(@"{
""FirstName"": ""Maurice"",
""LastName"": ""Moss"",
""BirthDate"": ""\/Date(252291661000)\/""
}", iPersonJson);
}
[Test]
public void SingleTypeWithMultipleContractResolvers()
{
@@ -127,4 +177,4 @@ namespace Newtonsoft.Json.Tests.Serialization
}", includeCompilerGeneratedJson);
}
}
}
}
@@ -1802,7 +1802,7 @@ keyword such as type of business.""
#endif
[Test]
[ExpectedException(typeof(JsonSerializationException), ExpectedMessage = @"Unable to find a constructor to use for type Newtonsoft.Json.Tests.TestObjects.Event. A class should either have a default constructor or only one constructor with arguments.")]
[ExpectedException(typeof(JsonSerializationException), ExpectedMessage = @"Unable to find a constructor to use for type Newtonsoft.Json.Tests.TestObjects.Event. A class should either have a default constructor, one constructor with arguments or a constructor marked with the JsonConstructor attribute.")]
public void FailWhenClassWithNoDefaultConstructorHasMultipleConstructorsWithArguments()
{
string json = @"{""sublocation"":""AlertEmailSender.Program.Main"",""userId"":0,""type"":0,""summary"":""Loading settings variables"",""details"":null,""stackTrace"":"" at System.Environment.GetStackTrace(Exception e, Boolean needFileInfo)\r\n at System.Environment.get_StackTrace()\r\n at mr.Logging.Event..ctor(String summary) in C:\\Projects\\MRUtils\\Logging\\Event.vb:line 71\r\n at AlertEmailSender.Program.Main(String[] args) in C:\\Projects\\AlertEmailSender\\AlertEmailSender\\Program.cs:line 25"",""tag"":null,""time"":""\/Date(1249591032026-0400)\/""}";
@@ -4043,5 +4043,86 @@ keyword such as type of business.""
Assert.AreEqual(decimal.MinValue, obj.Value);
}
public class NonPublicConstructorWithJsonConstructor
{
public string Value { get; private set; }
public string Constructor { get; private set; }
[JsonConstructor]
private NonPublicConstructorWithJsonConstructor()
{
Constructor = "NonPublic";
}
public NonPublicConstructorWithJsonConstructor(string value)
{
Value = value;
Constructor = "Public Paramatized";
}
}
[Test]
public void NonPublicConstructorWithJsonConstructorTest()
{
NonPublicConstructorWithJsonConstructor c = JsonConvert.DeserializeObject<NonPublicConstructorWithJsonConstructor>("{}");
Assert.AreEqual("NonPublic", c.Constructor);
}
public class PublicConstructorOverridenByJsonConstructor
{
public string Value { get; private set; }
public string Constructor { get; private set; }
public PublicConstructorOverridenByJsonConstructor()
{
Constructor = "NonPublic";
}
[JsonConstructor]
public PublicConstructorOverridenByJsonConstructor(string value)
{
Value = value;
Constructor = "Public Paramatized";
}
}
[Test]
public void PublicConstructorOverridenByJsonConstructorTest()
{
PublicConstructorOverridenByJsonConstructor c = JsonConvert.DeserializeObject<PublicConstructorOverridenByJsonConstructor>("{Value:'value!'}");
Assert.AreEqual("Public Paramatized", c.Constructor);
Assert.AreEqual("value!", c.Value);
}
public class MultipleParamatrizedConstructorsJsonConstructor
{
public string Value { get; private set; }
public int Age { get; private set; }
public string Constructor { get; private set; }
public MultipleParamatrizedConstructorsJsonConstructor(string value)
{
Value = value;
Constructor = "Public Paramatized 1";
}
[JsonConstructor]
public MultipleParamatrizedConstructorsJsonConstructor(string value, int age)
{
Value = value;
Age = age;
Constructor = "Public Paramatized 2";
}
}
[Test]
public void MultipleParamatrizedConstructorsJsonConstructorTest()
{
MultipleParamatrizedConstructorsJsonConstructor c = JsonConvert.DeserializeObject<MultipleParamatrizedConstructorsJsonConstructor>("{Value:'value!', Age:1}");
Assert.AreEqual("Public Paramatized 2", c.Constructor);
Assert.AreEqual("value!", c.Value);
Assert.AreEqual(1, c.Age);
}
}
}
@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Newtonsoft.Json
{
/// <summary>
/// Instructs the <see cref="JsonSerializer"/> not to serialize the public field or public read/write property value.
/// </summary>
[AttributeUsage(AttributeTargets.Constructor | AttributeTargets.Property, AllowMultiple = false)]
public sealed class JsonConstructorAttribute : Attribute
{
}
}
+5 -1
View File
@@ -32,6 +32,7 @@ using Newtonsoft.Json.Schema;
using Newtonsoft.Json.Utilities;
using System.Globalization;
using System.Text.RegularExpressions;
using System.IO;
namespace Newtonsoft.Json
{
@@ -300,8 +301,11 @@ namespace Newtonsoft.Json
if (schema.Enum != null)
{
StringWriter sw = new StringWriter(CultureInfo.InvariantCulture);
value.WriteTo(new JsonTextWriter(sw));
if (!schema.Enum.ContainsValue(value, new JTokenEqualityComparer()))
RaiseError("Value {0} is not defined in enum.".FormatWith(CultureInfo.InvariantCulture, value),
RaiseError("Value {0} is not defined in enum.".FormatWith(CultureInfo.InvariantCulture, sw.ToString()),
schema);
}
+55 -1
View File
@@ -40,7 +40,7 @@ namespace Newtonsoft.Json.Linq
/// <summary>
/// Represents a value in JSON (string, integer, date, etc).
/// </summary>
public class JValue : JToken, IEquatable<JValue>
public class JValue : JToken, IEquatable<JValue>, IFormattable
{
private JTokenType _valueType;
private object _value;
@@ -406,6 +406,40 @@ namespace Newtonsoft.Json.Linq
return _value.GetHashCode();
}
/// <summary>
/// Returns a <see cref="System.String"/> that represents this instance.
/// </summary>
/// <returns>
/// A <see cref="System.String"/> that represents this instance.
/// </returns>
public override string ToString()
{
if (_value == null)
return string.Empty;
return _value.ToString();
}
/// <summary>
/// Returns a <see cref="System.String"/> that represents this instance.
/// </summary>
/// <param name="format">The format.</param>
/// <param name="formatProvider">The format provider.</param>
/// <returns>
/// A <see cref="System.String"/> that represents this instance.
/// </returns>
public string ToString(string format, IFormatProvider formatProvider)
{
if (_value == null)
return string.Empty;
IFormattable formattable = _value as IFormattable;
if (formattable != null)
return formattable.ToString(format, formatProvider);
else
return _value.ToString();
}
#if !(NET35 || NET20 || WINDOWS_PHONE)
/// <summary>
/// Returns the <see cref="T:System.Dynamic.DynamicMetaObject"/> responsible for binding operations performed on this object.
@@ -440,6 +474,26 @@ namespace Newtonsoft.Json.Linq
result = ConvertUtils.Convert(instance.Value, CultureInfo.InvariantCulture, binder.Type);
return true;
}
//public override bool TryBinaryOperation(JValue instance, BinaryOperationBinder binder, object arg, out object result)
//{
// dynamic d1 = arg;
// dynamic d2 = instance._value;
// //// use built in JValue equals
// //if (arg is JValue)
// //{
// // result = null;
// // return false;
// //}
// //if (binder.Operation == ExpressionType.Equal)
// //{
// // result = Compare(instance.Type, instance.Value, arg);
// // return true;
// //}
// //return base.TryBinaryOperation(instance, binder, arg, out result);
//}
}
#endif
}
@@ -95,6 +95,7 @@
<Compile Include="Converters\KeyValuePairConverter.cs" />
<Compile Include="Converters\RegexConverter.cs" />
<Compile Include="Converters\StringEnumConverter.cs" />
<Compile Include="JsonConstructorAttribute.cs" />
<Compile Include="Linq\ComponentModel\JPropertyDescriptor.cs" />
<Compile Include="Linq\JPath.cs" />
<Compile Include="Linq\JRaw.cs" />
@@ -102,6 +102,7 @@
<Compile Include="Converters\RegexConverter.cs" />
<Compile Include="Converters\StringEnumConverter.cs" />
<Compile Include="ConstructorHandling.cs" />
<Compile Include="JsonConstructorAttribute.cs" />
<Compile Include="Utilities\DynamicProxy.cs" />
<Compile Include="Linq\JPath.cs" />
<Compile Include="Linq\JRaw.cs" />
@@ -106,6 +106,7 @@
<Compile Include="DefaultValueHandling.cs" />
<Compile Include="IJsonLineInfo.cs" />
<Compile Include="JsonArrayAttribute.cs" />
<Compile Include="JsonConstructorAttribute.cs" />
<Compile Include="JsonContainerAttribute.cs" />
<Compile Include="JsonConvert.cs" />
<Compile Include="JsonConverter.cs" />
@@ -79,6 +79,7 @@
<Compile Include="DefaultValueHandling.cs" />
<Compile Include="IJsonLineInfo.cs" />
<Compile Include="JsonArrayAttribute.cs" />
<Compile Include="JsonConstructorAttribute.cs" />
<Compile Include="JsonContainerAttribute.cs" />
<Compile Include="JsonConvert.cs" />
<Compile Include="JsonConverter.cs" />
@@ -101,6 +101,7 @@
<Compile Include="Converters\RegexConverter.cs" />
<Compile Include="Converters\StringEnumConverter.cs" />
<Compile Include="ConstructorHandling.cs" />
<Compile Include="JsonConstructorAttribute.cs" />
<Compile Include="Utilities\DynamicProxy.cs" />
<Compile Include="Linq\JPath.cs" />
<Compile Include="Linq\JRaw.cs" />
@@ -64,7 +64,7 @@ namespace Newtonsoft.Json.Serialization
if (!(obj is ResolverContractKey))
return false;
return Equals((ResolverContractKey) obj);
return Equals((ResolverContractKey)obj);
}
public bool Equals(ResolverContractKey other)
@@ -277,17 +277,31 @@ namespace Newtonsoft.Json.Serialization
contract.MemberSerialization = JsonTypeReflector.GetObjectMemberSerialization(objectType);
contract.Properties.AddRange(CreateProperties(contract.UnderlyingType, contract.MemberSerialization));
if (contract.DefaultCreator == null || contract.DefaultCreatorNonPublic)
if (objectType.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Any(c => c.IsDefined(typeof(JsonConstructorAttribute), true)))
contract.OverrideConstructor = GetAttributeConstructor(objectType);
else if (contract.DefaultCreator == null || contract.DefaultCreatorNonPublic)
contract.ParametrizedConstructor = GetParametrizedConstructor(objectType);
return contract;
}
private ConstructorInfo GetAttributeConstructor(Type objectType)
{
IList<ConstructorInfo> markedConstructors = objectType.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Where(c => c.IsDefined(typeof(JsonConstructorAttribute), true)).ToList();
if (markedConstructors.Count > 1)
throw new Exception("Multiple constructors with the JsonConstructorAttribute.");
else if (markedConstructors.Count == 1)
return markedConstructors[0];
return null;
}
private ConstructorInfo GetParametrizedConstructor(Type objectType)
{
ConstructorInfo[] constructors = objectType.GetConstructors(BindingFlags.Public | BindingFlags.Instance);
IList<ConstructorInfo> constructors = objectType.GetConstructors(BindingFlags.Public | BindingFlags.Instance);
if (constructors.Length == 1)
if (constructors.Count == 1)
return constructors[0];
else
return null;
@@ -309,7 +323,7 @@ namespace Newtonsoft.Json.Serialization
}
#if !PocketPC && !NET20
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Portability", "CA1903:UseOnlyApiFromTargetedFramework", MessageId = "System.Runtime.Serialization.DataContractAttribute.#get_IsReference()")]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Portability", "CA1903:UseOnlyApiFromTargetedFramework", MessageId = "System.Runtime.Serialization.DataContractAttribute.#get_IsReference()")]
#endif
private void InitializeContract(JsonContract contract)
{
@@ -412,7 +426,7 @@ namespace Newtonsoft.Json.Serialization
{
JsonPrimitiveContract contract = new JsonPrimitiveContract(objectType);
InitializeContract(contract);
return contract;
}
@@ -440,7 +454,7 @@ namespace Newtonsoft.Json.Serialization
JsonISerializableContract contract = new JsonISerializableContract(objectType);
InitializeContract(contract);
ConstructorInfo constructorInfo = objectType.GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, new [] {typeof (SerializationInfo), typeof (StreamingContext)}, null);
ConstructorInfo constructorInfo = objectType.GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, new[] { typeof(SerializationInfo), typeof(StreamingContext) }, null);
if (constructorInfo != null)
{
MethodCall<object, object> methodCall = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall<object>(constructorInfo);
@@ -574,7 +588,7 @@ namespace Newtonsoft.Json.Serialization
if (attributeType == typeof(OnErrorAttribute))
{
if (parameters == null || parameters.Length != 2 || parameters[0].ParameterType != typeof(StreamingContext) || parameters[1].ParameterType != typeof(ErrorContext))
throw new Exception("Serialization Error Callback '{1}' in type '{0}' must have two parameters of type '{2}' and '{3}'.".FormatWith(CultureInfo.InvariantCulture, GetClrTypeFullName(method.DeclaringType), method, typeof (StreamingContext), typeof(ErrorContext)));
throw new Exception("Serialization Error Callback '{1}' in type '{0}' must have two parameters of type '{2}' and '{3}'.".FormatWith(CultureInfo.InvariantCulture, GetClrTypeFullName(method.DeclaringType), method, typeof(StreamingContext), typeof(ErrorContext)));
}
else
{
@@ -646,7 +660,7 @@ namespace Newtonsoft.Json.Serialization
JsonProperty property = new JsonProperty();
property.PropertyType = ReflectionUtils.GetMemberUnderlyingType(member);
property.ValueProvider = CreateMemberValueProvider(member);
// resolve converter for property
// the class type might have a converter but the property converter takes presidence
property.Converter = JsonTypeReflector.GetJsonConverter(member, property.PropertyType);
@@ -689,7 +703,7 @@ namespace Newtonsoft.Json.Serialization
(memberSerialization == MemberSerialization.OptIn
&& propertyAttribute == null
#if !PocketPC && !NET20
&& dataMemberAttribute == null
&& dataMemberAttribute == null
#endif
));
@@ -735,7 +749,7 @@ namespace Newtonsoft.Json.Serialization
MethodCall<object, object> shouldSerializeCall =
JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall<object>(shouldSerializeMethod);
return o => (bool) shouldSerializeCall(o);
return o => (bool)shouldSerializeCall(o);
}
private void SetIsSpecifiedActions(JsonProperty property, MemberInfo member)
@@ -45,6 +45,14 @@ namespace Newtonsoft.Json.Serialization
/// <value>The object's properties.</value>
public JsonPropertyCollection Properties { get; private set; }
/// <summary>
/// Gets or sets the override constructor used to create the object.
/// This is set when a constructor is marked up using the
/// JsonConstructor attribute.
/// </summary>
/// <value>The override constructor.</value>
public ConstructorInfo OverrideConstructor { get; set; }
/// <summary>
/// Gets or sets the parametrized constructor used to create the object.
/// </summary>
@@ -831,27 +831,35 @@ namespace Newtonsoft.Json.Serialization
if (contract.UnderlyingType.IsInterface || contract.UnderlyingType.IsAbstract)
throw new JsonSerializationException("Could not create an instance of type {0}. Type is an interface or abstract class and cannot be instantated.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));
if (contract.DefaultCreator != null &&
if (contract.OverrideConstructor != null)
{
if (contract.OverrideConstructor.GetParameters().Length > 0)
return CreateObjectFromNonDefaultConstructor(reader, contract, contract.OverrideConstructor, id);
newObject = contract.OverrideConstructor.Invoke(null);
}
else if (contract.DefaultCreator != null &&
(!contract.DefaultCreatorNonPublic || Serializer.ConstructorHandling == ConstructorHandling.AllowNonPublicDefaultConstructor))
{
newObject = contract.DefaultCreator();
}
if (newObject != null)
else if (contract.ParametrizedConstructor != null)
{
PopulateObject(newObject, reader, contract, id);
return newObject;
return CreateObjectFromNonDefaultConstructor(reader, contract, contract.ParametrizedConstructor, id);
}
return CreateObjectFromNonDefaultConstructor(reader, contract, id);
if (newObject == null)
throw new JsonSerializationException("Unable to find a constructor to use for type {0}. A class should either have a default constructor, one constructor with arguments or a constructor marked with the JsonConstructor attribute.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));
PopulateObject(newObject, reader, contract, id);
return newObject;
}
private object CreateObjectFromNonDefaultConstructor(JsonReader reader, JsonObjectContract contract, string id)
private object CreateObjectFromNonDefaultConstructor(JsonReader reader, JsonObjectContract contract, ConstructorInfo constructorInfo, string id)
{
Type objectType = contract.UnderlyingType;
ValidationUtils.ArgumentNotNull(constructorInfo, "constructorInfo");
if (contract.ParametrizedConstructor == null)
throw new JsonSerializationException("Unable to find a constructor to use for type {0}. A class should either have a default constructor or only one constructor with arguments.".FormatWith(CultureInfo.InvariantCulture, objectType));
Type objectType = contract.UnderlyingType;
// create a dictionary to put retrieved values into
IDictionary<JsonProperty, object> propertyValues = contract.Properties.Where(p => !p.Ignored).ToDictionary(kv => kv, kv => (object)null);
@@ -897,7 +905,7 @@ namespace Newtonsoft.Json.Serialization
}
} while (!exit && reader.Read());
IDictionary<ParameterInfo, object> constructorParameters = contract.ParametrizedConstructor.GetParameters().ToDictionary(p => p, p => (object)null);
IDictionary<ParameterInfo, object> constructorParameters = constructorInfo.GetParameters().ToDictionary(p => p, p => (object)null);
IDictionary<JsonProperty, object> remainingPropertyValues = new Dictionary<JsonProperty, object>();
foreach (KeyValuePair<JsonProperty, object> propertyValue in propertyValues)
@@ -909,7 +917,7 @@ namespace Newtonsoft.Json.Serialization
remainingPropertyValues.Add(propertyValue);
}
object createdObject = contract.ParametrizedConstructor.Invoke(constructorParameters.Values.ToArray());
object createdObject = constructorInfo.Invoke(constructorParameters.Values.ToArray());
if (id != null)
Serializer.ReferenceResolver.AddReference(id, createdObject);
@@ -42,7 +42,7 @@ namespace Newtonsoft.Json.Utilities
{
DynamicMethod dynamicMethod = !owner.IsInterface
? new DynamicMethod(name, returnType, parameterTypes, owner, true)
: new DynamicMethod(name, returnType, parameterTypes, (Module)null, true);
: new DynamicMethod(name, returnType, parameterTypes, owner.Module, true);
return dynamicMethod;
}