diff --git a/Src/Newtonsoft.Json.Tests/EntityDataModel.Designer.cs b/Src/Newtonsoft.Json.Tests/EntityDataModel.Designer.cs
new file mode 100644
index 00000000..954fa14a
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/EntityDataModel.Designer.cs
@@ -0,0 +1,242 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:2.0.50727.3053
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+[assembly: global::System.Data.Objects.DataClasses.EdmSchemaAttribute()]
+[assembly: global::System.Data.Objects.DataClasses.EdmRelationshipAttribute("EntityDataModel", "PurchasePurchaseLine", "Purchase", global::System.Data.Metadata.Edm.RelationshipMultiplicity.One, typeof(Newtonsoft.Json.Tests.Purchase), "PurchaseLine", global::System.Data.Metadata.Edm.RelationshipMultiplicity.Many, typeof(Newtonsoft.Json.Tests.PurchaseLine))]
+
+// Original file name:
+// Generation date: 7/09/2008 7:58:08 p.m.
+namespace Newtonsoft.Json.Tests
+{
+
+ ///
+ /// There are no comments for EntityDataModelContainer in the schema.
+ ///
+ public partial class EntityDataModelContainer : global::System.Data.Objects.ObjectContext
+ {
+ ///
+ /// Initializes a new EntityDataModelContainer object using the connection string found in the 'EntityDataModelContainer' section of the application configuration file.
+ ///
+ public EntityDataModelContainer() :
+ base("name=EntityDataModelContainer", "EntityDataModelContainer")
+ {
+ this.OnContextCreated();
+ }
+ ///
+ /// Initialize a new EntityDataModelContainer object.
+ ///
+ public EntityDataModelContainer(string connectionString) :
+ base(connectionString, "EntityDataModelContainer")
+ {
+ this.OnContextCreated();
+ }
+ ///
+ /// Initialize a new EntityDataModelContainer object.
+ ///
+ public EntityDataModelContainer(global::System.Data.EntityClient.EntityConnection connection) :
+ base(connection, "EntityDataModelContainer")
+ {
+ this.OnContextCreated();
+ }
+ partial void OnContextCreated();
+ ///
+ /// There are no comments for PurchaseSet in the schema.
+ ///
+ public global::System.Data.Objects.ObjectQuery PurchaseSet
+ {
+ get
+ {
+ if ((this._PurchaseSet == null))
+ {
+ this._PurchaseSet = base.CreateQuery("[PurchaseSet]");
+ }
+ return this._PurchaseSet;
+ }
+ }
+ private global::System.Data.Objects.ObjectQuery _PurchaseSet;
+ ///
+ /// There are no comments for PurchaseLineSet in the schema.
+ ///
+ public global::System.Data.Objects.ObjectQuery PurchaseLineSet
+ {
+ get
+ {
+ if ((this._PurchaseLineSet == null))
+ {
+ this._PurchaseLineSet = base.CreateQuery("[PurchaseLineSet]");
+ }
+ return this._PurchaseLineSet;
+ }
+ }
+ private global::System.Data.Objects.ObjectQuery _PurchaseLineSet;
+ ///
+ /// There are no comments for PurchaseSet in the schema.
+ ///
+ public void AddToPurchaseSet(Purchase purchase)
+ {
+ base.AddObject("PurchaseSet", purchase);
+ }
+ ///
+ /// There are no comments for PurchaseLineSet in the schema.
+ ///
+ public void AddToPurchaseLineSet(PurchaseLine purchaseLine)
+ {
+ base.AddObject("PurchaseLineSet", purchaseLine);
+ }
+ }
+ ///
+ /// There are no comments for EntityDataModel.Purchase in the schema.
+ ///
+ ///
+ /// Id
+ ///
+ [global::System.Data.Objects.DataClasses.EdmEntityTypeAttribute(NamespaceName="EntityDataModel", Name="Purchase")]
+ [global::System.Runtime.Serialization.DataContractAttribute(IsReference=true)]
+ [global::System.Serializable()]
+ public partial class Purchase : global::System.Data.Objects.DataClasses.EntityObject
+ {
+ ///
+ /// Create a new Purchase object.
+ ///
+ /// Initial value of Id.
+ public static Purchase CreatePurchase(int id)
+ {
+ Purchase purchase = new Purchase();
+ purchase.Id = id;
+ return purchase;
+ }
+ ///
+ /// There are no comments for Property Id in the schema.
+ ///
+ [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(EntityKeyProperty=true, IsNullable=false)]
+ [global::System.Runtime.Serialization.DataMemberAttribute()]
+ public int Id
+ {
+ get
+ {
+ return this._Id;
+ }
+ set
+ {
+ this.OnIdChanging(value);
+ this.ReportPropertyChanging("Id");
+ this._Id = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value);
+ this.ReportPropertyChanged("Id");
+ this.OnIdChanged();
+ }
+ }
+ private int _Id;
+ partial void OnIdChanging(int value);
+ partial void OnIdChanged();
+ ///
+ /// There are no comments for PurchaseLine in the schema.
+ ///
+ [global::System.Data.Objects.DataClasses.EdmRelationshipNavigationPropertyAttribute("EntityDataModel", "PurchasePurchaseLine", "PurchaseLine")]
+ [global::System.Xml.Serialization.XmlIgnoreAttribute()]
+ [global::System.Xml.Serialization.SoapIgnoreAttribute()]
+ [global::System.Runtime.Serialization.DataMemberAttribute()]
+ public global::System.Data.Objects.DataClasses.EntityCollection PurchaseLine
+ {
+ get
+ {
+ return ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.GetRelatedCollection("EntityDataModel.PurchasePurchaseLine", "PurchaseLine");
+ }
+ set
+ {
+ if ((value != null))
+ {
+ ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.InitializeRelatedCollection("EntityDataModel.PurchasePurchaseLine", "PurchaseLine", value);
+ }
+ }
+ }
+ }
+ ///
+ /// There are no comments for EntityDataModel.PurchaseLine in the schema.
+ ///
+ ///
+ /// Id
+ ///
+ [global::System.Data.Objects.DataClasses.EdmEntityTypeAttribute(NamespaceName="EntityDataModel", Name="PurchaseLine")]
+ [global::System.Runtime.Serialization.DataContractAttribute(IsReference=true)]
+ [global::System.Serializable()]
+ public partial class PurchaseLine : global::System.Data.Objects.DataClasses.EntityObject
+ {
+ ///
+ /// Create a new PurchaseLine object.
+ ///
+ /// Initial value of Id.
+ public static PurchaseLine CreatePurchaseLine(int id)
+ {
+ PurchaseLine purchaseLine = new PurchaseLine();
+ purchaseLine.Id = id;
+ return purchaseLine;
+ }
+ ///
+ /// There are no comments for Property Id in the schema.
+ ///
+ [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(EntityKeyProperty=true, IsNullable=false)]
+ [global::System.Runtime.Serialization.DataMemberAttribute()]
+ public int Id
+ {
+ get
+ {
+ return this._Id;
+ }
+ set
+ {
+ this.OnIdChanging(value);
+ this.ReportPropertyChanging("Id");
+ this._Id = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value);
+ this.ReportPropertyChanged("Id");
+ this.OnIdChanged();
+ }
+ }
+ private int _Id;
+ partial void OnIdChanging(int value);
+ partial void OnIdChanged();
+ ///
+ /// There are no comments for Purchase in the schema.
+ ///
+ [global::System.Data.Objects.DataClasses.EdmRelationshipNavigationPropertyAttribute("EntityDataModel", "PurchasePurchaseLine", "Purchase")]
+ [global::System.Xml.Serialization.XmlIgnoreAttribute()]
+ [global::System.Xml.Serialization.SoapIgnoreAttribute()]
+ [global::System.Runtime.Serialization.DataMemberAttribute()]
+ public Purchase Purchase
+ {
+ get
+ {
+ return ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.GetRelatedReference("EntityDataModel.PurchasePurchaseLine", "Purchase").Value;
+ }
+ set
+ {
+ ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.GetRelatedReference("EntityDataModel.PurchasePurchaseLine", "Purchase").Value = value;
+ }
+ }
+ ///
+ /// There are no comments for Purchase in the schema.
+ ///
+ [global::System.ComponentModel.BrowsableAttribute(false)]
+ [global::System.Runtime.Serialization.DataMemberAttribute()]
+ public global::System.Data.Objects.DataClasses.EntityReference PurchaseReference
+ {
+ get
+ {
+ return ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.GetRelatedReference("EntityDataModel.PurchasePurchaseLine", "Purchase");
+ }
+ set
+ {
+ if ((value != null))
+ {
+ ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.InitializeRelatedReference("EntityDataModel.PurchasePurchaseLine", "Purchase", value);
+ }
+ }
+ }
+ }
+}
diff --git a/Src/Newtonsoft.Json.Tests/EntityDataModel.edmx b/Src/Newtonsoft.Json.Tests/EntityDataModel.edmx
new file mode 100644
index 00000000..aec3aa44
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/EntityDataModel.edmx
@@ -0,0 +1,67 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json.Tests/JavaScriptConvertTest.cs b/Src/Newtonsoft.Json.Tests/JavaScriptConvertTest.cs
index 44074958..0f65a8f0 100644
--- a/Src/Newtonsoft.Json.Tests/JavaScriptConvertTest.cs
+++ b/Src/Newtonsoft.Json.Tests/JavaScriptConvertTest.cs
@@ -28,11 +28,77 @@ using System.Collections.Generic;
using System.Text;
using Newtonsoft.Json.Utilities;
using NUnit.Framework;
+using System.IO;
+using System.Linq;
namespace Newtonsoft.Json.Tests
{
public class JavaScriptConvertTest : TestFixtureBase
{
+#if Entities
+ [Test]
+ public void EntitiesTest()
+ {
+ Purchase purchase = new Purchase() { Id = 1 };
+ purchase.PurchaseLine.Add(new PurchaseLine() { Id = 1, Purchase = purchase });
+ purchase.PurchaseLine.Add(new PurchaseLine() { Id = 2, Purchase = purchase });
+
+ StringWriter sw = new StringWriter();
+ JsonSerializer serializer = new JsonSerializer();
+ serializer.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
+
+ using (JsonWriter jw = new JsonTextWriter(sw))
+ {
+ jw.Formatting = Formatting.Indented;
+
+ serializer.Serialize(jw, purchase);
+ }
+
+ string json = sw.ToString();
+
+ Assert.AreEqual(@"{
+ ""Id"": 1,
+ ""PurchaseLine"": [
+ {
+ ""Id"": 1,
+ ""PurchaseReference"": {
+ ""EntityKey"": null,
+ ""RelationshipName"": ""EntityDataModel.PurchasePurchaseLine"",
+ ""SourceRoleName"": ""PurchaseLine"",
+ ""TargetRoleName"": ""Purchase"",
+ ""RelationshipSet"": null,
+ ""IsLoaded"": false
+ },
+ ""EntityState"": 1,
+ ""EntityKey"": null
+ },
+ {
+ ""Id"": 2,
+ ""PurchaseReference"": {
+ ""EntityKey"": null,
+ ""RelationshipName"": ""EntityDataModel.PurchasePurchaseLine"",
+ ""SourceRoleName"": ""PurchaseLine"",
+ ""TargetRoleName"": ""Purchase"",
+ ""RelationshipSet"": null,
+ ""IsLoaded"": false
+ },
+ ""EntityState"": 1,
+ ""EntityKey"": null
+ }
+ ],
+ ""EntityState"": 1,
+ ""EntityKey"": null
+}", json);
+
+ Purchase newPurchase = JavaScriptConvert.DeserializeObject(json);
+ Assert.AreEqual(1, newPurchase.Id);
+
+ Assert.AreEqual(2, newPurchase.PurchaseLine.Count);
+ Assert.AreEqual(1, newPurchase.PurchaseLine.ElementAt(0).Id);
+ Assert.AreEqual(2, newPurchase.PurchaseLine.ElementAt(1).Id);
+ }
+#endif
+
[Test]
public void EscapeJavaScriptString()
{
diff --git a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.csproj b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.csproj
index 234cadac..e4c5d2cf 100644
--- a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.csproj
+++ b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.csproj
@@ -51,9 +51,13 @@
3.5
+
+ 3.5
+
3.0
+
3.0
@@ -84,6 +88,7 @@
+
diff --git a/Src/Newtonsoft.Json.Tests/PerformanceTests.cs b/Src/Newtonsoft.Json.Tests/PerformanceTests.cs
new file mode 100644
index 00000000..382ce5ea
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/PerformanceTests.cs
@@ -0,0 +1,182 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Data;
+using System.Diagnostics;
+
+using Newtonsoft.Json;
+using System.IO;
+using System.Web.Script.Serialization;
+using NUnit.Framework;
+
+namespace Newtonsoft.Json.Tests
+{
+ ///
+ /// Summary description for JsonSerializerTest
+ ///
+ public class PerformanceTests : TestFixtureBase
+ {
+ private DateTime BaseDate = DateTime.Parse("01/01/2000");
+
+ //JSONSerializer ser = null;
+
+ public string SerializeJsonNet(object value)
+ {
+ Type type = value.GetType();
+
+ Newtonsoft.Json.JsonSerializer json = new Newtonsoft.Json.JsonSerializer();
+
+ json.NullValueHandling = NullValueHandling.Ignore;
+
+ json.ObjectCreationHandling = Newtonsoft.Json.ObjectCreationHandling.Replace;
+ json.MissingMemberHandling = Newtonsoft.Json.MissingMemberHandling.Ignore;
+ json.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
+
+
+ StringWriter sw = new StringWriter();
+ Newtonsoft.Json.JsonTextWriter writer = new JsonTextWriter(sw);
+
+ if (false)
+ writer.Formatting = Formatting.Indented;
+ else
+ writer.Formatting = Formatting.None;
+
+ writer.QuoteChar = '"';
+ json.Serialize(writer, value);
+
+ string output = sw.ToString();
+ writer.Close();
+
+ return output;
+ }
+
+ public string SerializeWebExtensions(object value)
+ {
+ JavaScriptSerializer ser = new JavaScriptSerializer();
+
+ List converters = new List();
+
+ return ser.Serialize(value);
+ }
+
+
+ [Test]
+ public void PerformanceTest2()
+ {
+
+ TestClass test = new TestClass();
+
+ test.Address1.Address = "fff Street";
+ test.Address1.Entered = DateTime.Now.AddDays(20);
+
+ test.BigNumber = 34123123123.121M;
+ test.Now = DateTime.Now.AddHours(1);
+ test.strings = new List() { "Rick", "Markus egger ][, (2nd)", "Kevin McNeish" };
+
+ cAddress address = new cAddress();
+ address.Entered = DateTime.Now.AddDays(-1);
+ address.Address = "array address";
+
+ test.Addresses.Add(address);
+
+ address = new cAddress();
+ address.Entered = DateTime.Now.AddDays(-2);
+ address.Address = "array 2 address";
+ test.Addresses.Add(address);
+
+ Stopwatch timed = new Stopwatch();
+ timed.Start();
+
+ string json = null;
+ for (int x = 0; x < 10000; x++)
+ {
+ json = this.SerializeJsonNet(test);
+ //json = this.SerializeWebExtensions(test);
+ }
+ timed.Stop();
+
+ Console.WriteLine("{0}", timed.ElapsedMilliseconds + " ms");
+ Console.WriteLine("{0}", json);
+ }
+ }
+
+
+ public class TestClass
+ {
+
+ public string Name
+ {
+ get { return _Name; }
+ set { _Name = value; }
+ }
+ private string _Name = "Rick";
+
+
+ public DateTime Now
+ {
+ get { return _Now; }
+ set { _Now = value; }
+ }
+ private DateTime _Now = DateTime.Now;
+
+
+ public decimal BigNumber
+ {
+ get { return _BigNumber; }
+ set { _BigNumber = value; }
+ }
+ private decimal _BigNumber = 1212121.22M;
+
+
+ public cAddress Address1
+ {
+ get { return _Address1; }
+ set { _Address1 = value; }
+ }
+ private cAddress _Address1 = new cAddress();
+
+
+
+
+ public List Addresses
+ {
+ get { return _Addresses; }
+ set { _Addresses = value; }
+ }
+ private List _Addresses = new List();
+
+
+ public List strings = new List() { "Rick", "Markus", "Kevin" };
+
+
+ public Dictionary dictionary = new Dictionary { { "Val asd1", 1 }, { "Val2", 3 }, { "Val3", 4 } };
+ }
+
+ public class cAddress
+ {
+
+ public string Address
+ {
+ get { return _Address; }
+ set { _Address = value; }
+ }
+ private string _Address = "32 Kaiea";
+
+
+ public string Phone
+ {
+ get { return _Phone; }
+ set { _Phone = value; }
+ }
+ private string _Phone = "(503) 814-6335";
+
+
+ public DateTime Entered
+ {
+ get { return _Entered; }
+ set { _Entered = value; }
+ }
+ private DateTime _Entered = DateTime.Parse("01/01/2007", CultureInfo.CurrentCulture.DateTimeFormat);
+
+ }
+}
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json/JsonConverterAttribute.cs b/Src/Newtonsoft.Json/JsonConverterAttribute.cs
index 9ee2dcfa..cd92ed0a 100644
--- a/Src/Newtonsoft.Json/JsonConverterAttribute.cs
+++ b/Src/Newtonsoft.Json/JsonConverterAttribute.cs
@@ -36,15 +36,15 @@ namespace Newtonsoft.Json
_converterType = converterType;
}
- internal JsonConverter CreateJsonConverterInstance()
+ internal static JsonConverter CreateJsonConverterInstance(Type converterType)
{
try
{
- return (JsonConverter)Activator.CreateInstance(_converterType);
+ return (JsonConverter)Activator.CreateInstance(converterType);
}
catch (Exception ex)
{
- throw new Exception("Error creating {0}".FormatWith(CultureInfo.InvariantCulture, _converterType), ex);
+ throw new Exception("Error creating {0}".FormatWith(CultureInfo.InvariantCulture, converterType), ex);
}
}
}
diff --git a/Src/Newtonsoft.Json/JsonSerializer.cs b/Src/Newtonsoft.Json/JsonSerializer.cs
index 2cfabe3f..2e70532c 100644
--- a/Src/Newtonsoft.Json/JsonSerializer.cs
+++ b/Src/Newtonsoft.Json/JsonSerializer.cs
@@ -44,13 +44,15 @@ namespace Newtonsoft.Json
///
public class JsonSerializer
{
+ private static readonly Dictionary ConverterTypeCache = new Dictionary();
+ private static Dictionary TypeMemberMappings = new Dictionary();
+
private ReferenceLoopHandling _referenceLoopHandling;
private MissingMemberHandling _missingMemberHandling;
private ObjectCreationHandling _objectCreationHandling;
private NullValueHandling _nullValueHandling;
private int _level;
private JsonConverterCollection _converters;
- private Dictionary _typeMemberMappings;
///
/// Get or set how reference loops (e.g. a class referencing itself) is handled.
@@ -255,7 +257,7 @@ namespace Newtonsoft.Json
if (existingValue == null)
value = CreateAndPopulateList(reader, objectType);
else
- value = PopulateList(CollectionUtils.CreateListWrapper(existingValue), ReflectionUtils.GetListItemType(objectType), reader);
+ value = PopulateList(CollectionUtils.CreateCollectionWrapper(existingValue), ReflectionUtils.GetCollectionItemType(objectType), reader);
}
else
{
@@ -317,16 +319,13 @@ namespace Newtonsoft.Json
private MemberMappingCollection GetMemberMappings(Type objectType)
{
- if (_typeMemberMappings == null)
- _typeMemberMappings = new Dictionary();
-
MemberMappingCollection memberMappings;
- if (_typeMemberMappings.TryGetValue(objectType, out memberMappings))
+ if (TypeMemberMappings.TryGetValue(objectType, out memberMappings))
return memberMappings;
memberMappings = CreateMemberMappings(objectType);
- _typeMemberMappings[objectType] = memberMappings;
+ TypeMemberMappings[objectType] = memberMappings;
return memberMappings;
}
@@ -388,11 +387,25 @@ namespace Newtonsoft.Json
private JsonConverter GetConverter(ICustomAttributeProvider attributeProvider, Type targetConvertedType)
{
- JsonConverterAttribute converterAttribute = ReflectionUtils.GetAttribute(attributeProvider, true);
+ Type converterType;
- if (converterAttribute != null)
+ if (!ConverterTypeCache.ContainsKey(attributeProvider))
{
- JsonConverter memberConverter = converterAttribute.CreateJsonConverterInstance();
+ JsonConverterAttribute converterAttribute = ReflectionUtils.GetAttribute(attributeProvider, true);
+ converterType = (converterAttribute != null)
+ ? converterAttribute.ConverterType
+ : null;
+
+ ConverterTypeCache[attributeProvider] = converterType;
+ }
+ else
+ {
+ converterType = ConverterTypeCache[attributeProvider];
+ }
+
+ if (converterType != null)
+ {
+ JsonConverter memberConverter = JsonConverterAttribute.CreateJsonConverterInstance(converterType);
if (!memberConverter.CanConvert(targetConvertedType))
throw new JsonSerializationException("JsonConverter {0} on {1} is not compatible with member type {2}.".FormatWith(CultureInfo.InvariantCulture, memberConverter.GetType().Name, attributeProvider, targetConvertedType.Name));
@@ -490,7 +503,7 @@ namespace Newtonsoft.Json
private object CreateAndPopulateList(JsonReader reader, Type objectType)
{
- return CollectionUtils.CreateAndPopulateList(objectType, l => PopulateList(l, ReflectionUtils.GetListItemType(objectType), reader));
+ return CollectionUtils.CreateAndPopulateList(objectType, l => PopulateList(l, ReflectionUtils.GetCollectionItemType(objectType), reader));
}
private IList PopulateList(IList list, Type listItemType, JsonReader reader)
diff --git a/Src/Newtonsoft.Json/Newtonsoft.Json.csproj b/Src/Newtonsoft.Json/Newtonsoft.Json.csproj
index 1b50a976..2b9553c4 100644
--- a/Src/Newtonsoft.Json/Newtonsoft.Json.csproj
+++ b/Src/Newtonsoft.Json/Newtonsoft.Json.csproj
@@ -116,6 +116,7 @@
+
diff --git a/Src/Newtonsoft.Json/Utilities/CollectionUtils.cs b/Src/Newtonsoft.Json/Utilities/CollectionUtils.cs
index 56736cca..ac07f550 100644
--- a/Src/Newtonsoft.Json/Utilities/CollectionUtils.cs
+++ b/Src/Newtonsoft.Json/Utilities/CollectionUtils.cs
@@ -366,6 +366,33 @@ namespace Newtonsoft.Json.Utilities
return false;
}
+ public static IWrappedCollection CreateCollectionWrapper(object list)
+ {
+ ValidationUtils.ArgumentNotNull(list, "list");
+
+ Type collectionDefinition;
+ if (ReflectionUtils.IsSubClass(list.GetType(), typeof(ICollection<>), out collectionDefinition))
+ {
+ Type collectionItemType = ReflectionUtils.GetCollectionItemType(collectionDefinition);
+
+ // Activator.CreateInstance throws AmbiguousMatchException. Manually invoke constructor
+ Func, object> instanceCreator = (t, a) =>
+ {
+ ConstructorInfo c = t.GetConstructor(new[] { collectionDefinition });
+ return c.Invoke(new[] { list });
+ };
+
+ return (IWrappedCollection)ReflectionUtils.CreateGeneric(typeof(CollectionWrapper<>), new[] { collectionItemType }, instanceCreator, list);
+ }
+ else if (list is IList)
+ {
+ return new CollectionWrapper