1. Greg Dennis
  2. Manatee.Json

Commits

gde...@USGVL36T22M1.babgsetc.pvt  committed 7491815

Changed serializer usage of reference cache to maintain as thread static

  • Participants
  • Parent commits fd10ff8
  • Branches default

Comments (0)

Files changed (6)

File Json.Tests/Json/Serialization/JsonSerializerTest.cs

View file
 			Assert.AreEqual(expected.LoopProperty.StringProp, actual.LoopProperty.StringProp);
 			Assert.IsNotNull(actual.LoopProperty.LoopProperty);
 			Assert.AreSame(actual, actual.LoopProperty.LoopProperty);
-
 		}
 		#endregion
 

File Json.sln.docstates.suo

Binary file modified.

File Json.suo

Binary file modified.

File Json/Helpers/SerializerMethodPair.cs

View file
 
 		private static MethodInfo GetTypedSerializeMethod(Type type)
 		{
-			return typeof(JsonSerializer).GetMethod("ManagedSerialize", BindingFlags.Instance | BindingFlags.NonPublic)
+			return typeof(JsonSerializer).GetMethod("Serialize")
 										 .MakeGenericMethod(type);
 		}
 		private static MethodInfo GetTypedDeserializeMethod(Type type)
 		{
-			return typeof(JsonSerializer).GetMethod("ManagedDeserialize", BindingFlags.Instance | BindingFlags.NonPublic)
+			return typeof(JsonSerializer).GetMethod("Deserialize")
 										 .MakeGenericMethod(type);
 		}
 	}

File Json/Serialization/JsonSerializationTypeRegistry.cs

View file
 		/// <returns>The JSON representation of the List&lt;T&gt;.</returns>
 		public static JsonValue EncodeGenericList<T>(List<T> list)
 		{
-			var cache = new SerializerReferenceCache();
 			var array = new JsonArray();
-			array.AddRange(list.Select(item => _serializer.ManagedSerialize(item, cache)));
-			cache.ReconcileJsonReferences();
+			array.AddRange(list.Select(item => _serializer.Serialize(item)));
 			return array;
 		}
 		/// <summary>
 		/// <returns>The List&lt;T&gt; object.</returns>
 		public static List<T> DecodeGenericList<T>(JsonValue json)
 		{
-			var cache = new SerializerReferenceCache();
 			var list = new List<T>();
-			list.AddRange(json.Array.Select(jv => _serializer.ManagedDeserialize<T>(jv, cache)));
-			cache.ReconcileObjectReferences();
+			list.AddRange(json.Array.Select(jv => _serializer.Deserialize<T>(jv)));
 			return list;
 		}
 		#endregion
 		/// <returns>The JSON representation of the Dictionary&lt;T&gt;.</returns>
 		public static JsonValue EncodeGenericDictionary<TKey, TValue>(Dictionary<TKey, TValue> dict)
 		{
-			var cache = new SerializerReferenceCache();
 			var array = new JsonArray();
 			array.AddRange(dict.Select(item => (JsonValue)(new JsonObject
 			                                               	{
-			                                               		{"Key", _serializer.ManagedSerialize(item.Key, cache)},
-																{"Value", _serializer.ManagedSerialize(item.Value, cache)}
+			                                               		{"Key", _serializer.Serialize(item.Key)},
+																{"Value", _serializer.Serialize(item.Value)}
 			                                               	})));
-			cache.ReconcileJsonReferences();
 			return array;
 		}
 		/// <summary>
 		/// <returns>The Dictionary&lt;T&gt; object.</returns>
 		public static Dictionary<TKey, TValue> DecodeGenericDictionary<TKey, TValue>(JsonValue json)
 		{
-			var cache = new SerializerReferenceCache();
 			var dict = new Dictionary<TKey, TValue>();
 			foreach (var jv in json.Array)
 			{
-				dict.Add(_serializer.ManagedDeserialize<TKey>(jv.Object["Key"], cache),
-						 _serializer.ManagedDeserialize<TValue>(jv.Object["Value"], cache));
+				dict.Add(_serializer.Deserialize<TKey>(jv.Object["Key"]),
+						 _serializer.Deserialize<TValue>(jv.Object["Value"]));
 			}
-			cache.ReconcileObjectReferences();
 			return dict;
 		}
 		#endregion
 		/// <returns>The JSON representation of the Queue&lt;T&gt;.</returns>
 		public static JsonValue EncodeGenericQueue<T>(Queue<T> queue)
 		{
-			var cache = new SerializerReferenceCache();
 			var array = new JsonArray();
 			for (int i = 0; i < queue.Count; i++)
 			{
-				array.Add(_serializer.ManagedSerialize(queue.ElementAt(i), cache));
+				array.Add(_serializer.Serialize(queue.ElementAt(i)));
 			}
-			cache.ReconcileJsonReferences();
 			return array;
 		}
 		/// <summary>
 		/// <returns>The Queue&lt;T&gt; object.</returns>
 		public static Queue<T> DecodeGenericQueue<T>(JsonValue json)
 		{
-			var cache = new SerializerReferenceCache();
 			var queue = new Queue<T>();
 			for (int i = 0; i < json.Array.Count; i++)
 			{
-				queue.Enqueue(_serializer.ManagedDeserialize<T>(json.Array[i], cache));
+				queue.Enqueue(_serializer.Deserialize<T>(json.Array[i]));
 			}
-			cache.ReconcileObjectReferences();
 			return queue;
 		}
 		#endregion
 		/// <returns>The JSON representation of the Stack&lt;T&gt;.</returns>
 		public static JsonValue EncodeGenericStack<T>(Stack<T> stack)
 		{
-			var cache = new SerializerReferenceCache();
 			var array = new JsonArray();
 			for (int i = 0; i < stack.Count; i++)
 			{
-				array.Add(_serializer.ManagedSerialize(stack.ElementAt(i), cache));
+				array.Add(_serializer.Serialize(stack.ElementAt(i)));
 			}
-			cache.ReconcileJsonReferences();
 			return array;
 		}
 		/// <summary>
 		/// <returns>The Stack&lt;T&gt; object.</returns>
 		public static Stack<T> DecodeGenericStack<T>(JsonValue json)
 		{
-			var cache = new SerializerReferenceCache();
 			var stack = new Stack<T>();
 			for (int i = 0; i < json.Array.Count; i++)
 			{
-				stack.Push(_serializer.ManagedDeserialize<T>(json.Array[i], cache));
+				stack.Push(_serializer.Deserialize<T>(json.Array[i]));
 			}
-			cache.ReconcileObjectReferences();
 			return stack;
 		}
 		#endregion

File Json/Serialization/JsonSerializer.cs

View file
 		private const string RefKey = "#Ref";
 		private const string DefKey = "#Define";
 
+		[ThreadStatic]
+		private SerializerReferenceCache _cache = new SerializerReferenceCache();
+		[ThreadStatic]
+		private int _callCount = 0;
+
 		/// <summary>
 		/// Gets or sets a set of options for the serializer.
 		/// </summary>
 		/// <returns>The JSON representation of the object.</returns>
 		public JsonValue Serialize<T>(T obj)
 		{
-			var cache = new SerializerReferenceCache();
-			var json = ManagedSerialize(obj, cache);
-			cache.ReconcileJsonReferences();
+			_callCount++;
+			var json = ManagedSerialize(obj);
+			if (--_callCount == 0)
+			{
+				_cache.ReconcileJsonReferences();
+				_cache.Clear();
+			}
 			return json;
 		}
 		/// <summary>
 		/// <returns>The JSON representation of the type.</returns>
 		public JsonValue SerializeType<T>()
 		{
-			var cache = new SerializerReferenceCache();
+			_callCount++;
 			VerifyOptions();
 			var json = new JsonObject();
 			var propertyInfoList = typeof(T).GetProperties(BindingFlags.Static | BindingFlags.Public)
 								? value.GetType()
 								: propertyInfo.PropertyType;
 					var serialize = SerializerCache.Instance.GetSerializer(type);
-					json.Add(propertyInfo.Name, (JsonValue) serialize.Invoke(this, new[] {value, cache}));
+					json.Add(propertyInfo.Name, (JsonValue) serialize.Invoke(this, new[] {value}));
 				}
 			}
-			cache.ReconcileJsonReferences();
+			if (--_callCount == 0)
+			{
+				_cache.ReconcileObjectReferences();
+				_cache.Clear();
+			}
 			return json.Count == 0 ? JsonValue.Null : json;
 		}
 		/// <summary>
 		/// <returns>The deserialized object.</returns>
 		public T Deserialize<T>(JsonValue json)
 		{
-			var cache = new SerializerReferenceCache();
-			var obj = ManagedDeserialize<T>(json, cache);
-			cache.ReconcileObjectReferences();
+			_callCount++;
+			var obj = ManagedDeserialize<T>(json);
+			if (--_callCount == 0)
+			{
+				_cache.ReconcileObjectReferences();
+				_cache.Clear();
+			}
 			return obj;
 		}
 		/// <summary>
 		/// <param name="json">The JSON representation of the type.</param>
 		public void DeserializeType<T>(JsonValue json)
 		{
-			var cache = new SerializerReferenceCache();
+			_callCount++;
 			VerifyOptions();
 			if (json == JsonValue.Null)
 				return;
 				if (json.Object.ContainsKey(propertyInfo.Name))
 				{
 					var deserialize = SerializerCache.Instance.GetDeserializer(propertyInfo.PropertyType);
-					propertyInfo.SetValue(null, deserialize.Invoke(this, new object[] {json.Object[propertyInfo.Name], cache}), null);
+					propertyInfo.SetValue(null, deserialize.Invoke(this, new object[] {json.Object[propertyInfo.Name]}), null);
 					json.Object.Remove(propertyInfo.Name);
 				}
 			}
-			cache.ReconcileObjectReferences();
+			if (--_callCount == 0)
+			{
+				_cache.ReconcileObjectReferences();
+				_cache.Clear();
+			}
 			if (json.Object.Count > 0)
 				throw new TypeDoesNotContainPropertyException(typeof(T), json);
 		}
 		#endregion
 
 		#region Support Methods
-		internal JsonValue ManagedSerialize<T>(T obj, SerializerReferenceCache cache)
+		private JsonValue ManagedSerialize<T>(T obj)
 		{
-			var match = cache.FindRecord(obj);
+			var match = _cache.FindRecord(obj);
 			if (match != null)
 			{
 				match.IsReferenced = true;
 				return new JsonObject {{RefKey, match.ReferenceID.ToString()}};
 			}
 			match = new SerializerReferenceRecord { Object = obj };
-			cache.Add(match);
+			_cache.Add(match);
 			VerifyOptions();
 			if (typeof(IJsonCompatible).IsAssignableFrom(typeof(T)))
 			{
 				if (match.Json == JsonValue.Null)
 				{
 					JsonValue json;
-					match.Json = this.TryEncode(obj, out json) ? json : AutoSerializeObject(obj, cache);
+					match.Json = this.TryEncode(obj, out json) ? json : AutoSerializeObject(obj);
 				}
 			}
 			return match.Json;
 		}
-		internal T ManagedDeserialize<T>(JsonValue json, SerializerReferenceCache cache)
+		private T ManagedDeserialize<T>(JsonValue json)
 		{
 			SerializerReferenceRecord match = null;
 			switch (json.Type)
 			{
 				case JsonValueType.Object:
 					if (json.Object.ContainsKey(DefKey))
-						cache.Add(match = new SerializerReferenceRecord(json.Object[DefKey].String));
+						_cache.Add(match = new SerializerReferenceRecord(json.Object[DefKey].String));
 					break;
 				case JsonValueType.Array:
 					var def = json.Array.Where(jv => (jv.Type == JsonValueType.Object) &&
 					                                 jv.Object.ContainsKey(DefKey))
 										.FirstOrDefault();
 					if (def != null)
-						cache.Add(match = new SerializerReferenceRecord(def.Object[DefKey].String));
+						_cache.Add(match = new SerializerReferenceRecord(def.Object[DefKey].String));
 					break;
 			}
 			VerifyOptions();
 			}
 			else if (!this.TryDecode(json, out obj))
 			{
-				obj = AutoDeserializeObject<T>(json, cache);
+				obj = AutoDeserializeObject<T>(json);
 			}
 			if (match != null)
 				match.Object = obj;
 			if (Options == null)
 				Options = JsonSerializerOptions.Default;
 		}
-		private JsonValue AutoSerializeObject<T>(T obj, SerializerReferenceCache cache)
+		private JsonValue AutoSerializeObject<T>(T obj)
 		{
 			var json = new JsonObject();
 			var propertyInfoList = typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public)
 					        ? value.GetType()
 					        : propertyInfo.PropertyType;
 				var serialize = SerializerCache.Instance.GetSerializer(type);
-				var jsonProp = (JsonValue) serialize.Invoke(this, new[] {value, cache});
+				var jsonProp = (JsonValue) serialize.Invoke(this, new[] {value});
 				if ((jsonProp == JsonValue.Null) && !Options.EncodeDefaultValues) continue;
 				json.Add(propertyInfo.Name,
 				         type == propertyInfo.PropertyType
 			}
 			return json.Count == 0 ? JsonValue.Null : json;
 		}
-		private T AutoDeserializeObject<T>(JsonValue json, SerializerReferenceCache cache)
+		private T AutoDeserializeObject<T>(JsonValue json)
 		{
 			var propertyInfoList = typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public)
 											.Where(p => p.GetSetMethod() != null)
 						var instanceType = Type.GetType(value.Object[TypeKey].String);
 						var instanceJson = value.Object[ValueKey];
 						var deserialize = SerializerCache.Instance.GetDeserializer(instanceType);
-						propertyInfo.SetValue(obj, deserialize.Invoke(this, new object[] {instanceJson, cache}), null);
+						propertyInfo.SetValue(obj, deserialize.Invoke(this, new object[] {instanceJson}), null);
 					}
 					else if ((value.Type == JsonValueType.Object) && (value.Object.ContainsKey(RefKey)))
 					{
-						cache.AddReference(value.Object[RefKey].String, obj, propertyInfo);
+						_cache.AddReference(value.Object[RefKey].String, obj, propertyInfo);
 					}
 					else
 					{
 						var deserialize = SerializerCache.Instance.GetDeserializer(propertyInfo.PropertyType);
-						propertyInfo.SetValue(obj, deserialize.Invoke(this, new object[] { json.Object[propertyInfo.Name], cache }), null);
+						propertyInfo.SetValue(obj, deserialize.Invoke(this, new object[] {json.Object[propertyInfo.Name]}), null);
 					}
 					json.Object.Remove(propertyInfo.Name);
 				}