-Improved Portable40 assembly performance by using compiled expression reflection

-Fixed converting string JValues to enums with JToken.ToObject
This commit is contained in:
James Newton-King
2014-08-24 23:33:08 +12:00
parent dce6228b8f
commit 57ccaf00bf
15 changed files with 125 additions and 21 deletions
@@ -137,8 +137,45 @@ namespace Newtonsoft.Json.Tests.Converters
Assert.IsNull(foo2.Bar);
}
[Test]
public void MultipleNamespacesXDocument()
{
string xml = @"<result xp_0:end=""2014-08-15 13:12:11.9184"" xp_0:start=""2014-08-15 13:11:49.3140"" xp_0:time_diff=""22604.3836"" xmlns:xp_0=""Test1"" p2:end=""2014-08-15 13:13:49.5522"" p2:start=""2014-08-15 13:13:49.0268"" p2:time_diff=""525.4646"" xmlns:p2=""Test2"" />";
XDocument d = XDocument.Parse(xml);
string json = JsonConvert.SerializeObject(d, Formatting.Indented);
Console.WriteLine(json);
XDocument doc = JsonConvert.DeserializeObject<XDocument>(json);
Console.WriteLine(doc.ToString());
Assert.AreEqual(xml, doc.ToString());
}
#endif
[Test]
public void MultipleNamespacesXmlDocument()
{
string xml = @"<result xp_0:end=""2014-08-15 13:12:11.9184"" xp_0:start=""2014-08-15 13:11:49.3140"" xp_0:time_diff=""22604.3836"" xmlns:xp_0=""Test1"" p2:end=""2014-08-15 13:13:49.5522"" p2:start=""2014-08-15 13:13:49.0268"" p2:time_diff=""525.4646"" xmlns:p2=""Test2"" />";
XmlDocument d = new XmlDocument();
d.LoadXml(xml);
string json = JsonConvert.SerializeObject(d, Formatting.Indented);
Console.WriteLine(json);
XmlDocument doc = JsonConvert.DeserializeObject<XmlDocument>(json);
Console.WriteLine(doc.OuterXml);
Assert.AreEqual(xml, doc.OuterXml);
}
[Test]
public void SerializeXmlElement()
{
@@ -444,6 +444,9 @@ namespace Newtonsoft.Json.Tests.Linq
ExceptionAssert.Throws<ArgumentException>("Can not convert Date to SByte.", () => { var i = (sbyte?)new JValue(DateTime.Now); });
ExceptionAssert.Throws<ArgumentException>("Can not convert Date to SByte.", () => { var i = (sbyte)new JValue(DateTime.Now); });
ExceptionAssert.Throws<ArgumentException>("Could not convert 'Ordinal1' to StringComparison.", () => { var i = (new JValue("Ordinal1")).ToObject<StringComparison>(); });
ExceptionAssert.Throws<ArgumentException>("Could not convert 'Ordinal1' to StringComparison.", () => { var i = (new JValue("Ordinal1")).ToObject<StringComparison?>(); });
}
[Test]
@@ -492,6 +495,9 @@ namespace Newtonsoft.Json.Tests.Linq
Assert.AreEqual(new Guid("A34B2080-B5F0-488E-834D-45D44ECB9E5C"), (new JValue(new Guid("A34B2080-B5F0-488E-834D-45D44ECB9E5C")).ToObject(typeof(Guid))));
Assert.AreEqual(new Guid("A34B2080-B5F0-488E-834D-45D44ECB9E5C"), (new JValue(new Guid("A34B2080-B5F0-488E-834D-45D44ECB9E5C")).ToObject(typeof(Guid?))));
Assert.AreEqual(new Uri("http://www.google.com/"), (new JValue(new Uri("http://www.google.com/")).ToObject(typeof(Uri))));
Assert.AreEqual(StringComparison.Ordinal, (new JValue("Ordinal").ToObject(typeof(StringComparison))));
Assert.AreEqual(StringComparison.Ordinal, (new JValue("Ordinal").ToObject(typeof(StringComparison?))));
Assert.AreEqual(null, (JValue.CreateNull().ToObject(typeof(StringComparison?))));
}
[Test]
@@ -755,5 +755,47 @@ namespace Newtonsoft.Json.Tests.Linq
""name"": ""Hello World""
}", json);
}
#if !(NET20 || NET35 || PORTABLE40)
[Test]
public void EnumTests()
{
JValue v = new JValue(StringComparison.Ordinal);
Assert.AreEqual(JTokenType.Integer, v.Type);
string s = v.ToString();
Assert.AreEqual("Ordinal", s);
StringComparison e = v.ToObject<StringComparison>();
Assert.AreEqual(StringComparison.Ordinal, e);
dynamic d = new JValue(StringComparison.CurrentCultureIgnoreCase);
StringComparison e2 = (StringComparison)d;
Assert.AreEqual(StringComparison.CurrentCultureIgnoreCase, e2);
string s1 = d.ToString();
Assert.AreEqual("CurrentCultureIgnoreCase", s1);
string s2 = (string)d;
Assert.AreEqual("CurrentCultureIgnoreCase", s2);
d = new JValue("OrdinalIgnoreCase");
StringComparison e3 = (StringComparison)d;
Assert.AreEqual(StringComparison.OrdinalIgnoreCase, e3);
v = new JValue("ORDINAL");
d = v;
StringComparison e4 = (StringComparison)d;
Assert.AreEqual(StringComparison.Ordinal, e4);
StringComparison e5 = v.ToObject<StringComparison>();
Assert.AreEqual(StringComparison.Ordinal, e5);
v = new JValue((int)StringComparison.InvariantCultureIgnoreCase);
Assert.AreEqual(JTokenType.Integer, v.Type);
StringComparison e6 = v.ToObject<StringComparison>();
Assert.AreEqual(StringComparison.InvariantCultureIgnoreCase, e6);
}
#endif
}
}
@@ -75,4 +75,4 @@ using System.Security;
// by using the '*' as shown below:
[assembly: AssemblyVersion("6.0.0.0")]
[assembly: AssemblyFileVersion("6.0.4.17603")]
[assembly: AssemblyFileVersion("6.0.4.17624")]
@@ -23,7 +23,7 @@
// OTHER DEALINGS IN THE SOFTWARE.
#endregion
#if !(PORTABLE40 || NET20 || NET35)
#if !(NET20 || NET35)
using System;
using System.Diagnostics;
using System.Reflection;
@@ -299,5 +299,4 @@ namespace Newtonsoft.Json.Tests.Utilities
}
}
}
#endif
+1 -2
View File
@@ -40,7 +40,6 @@ using Newtonsoft.Json.Serialization;
using System.Text;
#if !(NET20 || PORTABLE40)
using System.Xml.Linq;
#endif
namespace Newtonsoft.Json
@@ -434,7 +433,7 @@ namespace Newtonsoft.Json
if (value == null)
return Null;
PrimitiveTypeCode typeCode = ConvertUtils.GetTypeCode(value);
PrimitiveTypeCode typeCode = ConvertUtils.GetTypeCode(value.GetType());
switch (typeCode)
{
+1 -1
View File
@@ -1226,7 +1226,7 @@ namespace Newtonsoft.Json
throw CreateUnsupportedTypeException(this, value);
#endif
WriteValue(this, ConvertUtils.GetTypeCode(value), value);
WriteValue(this, ConvertUtils.GetTypeCode(value.GetType()), value);
}
}
#endregion
+1 -1
View File
@@ -32,7 +32,7 @@ namespace Newtonsoft.Json.Linq
/// </summary>
/// <typeparam name="T">The type of token</typeparam>
public interface IJEnumerable<
#if !(NET20 || NET35 || PORTABLE40)
#if !(NET20 || NET35)
out
#endif
T> : IEnumerable<T> where T : JToken
+15 -1
View File
@@ -1701,7 +1701,21 @@ namespace Newtonsoft.Json.Linq
{
if (JsonConvert.DefaultSettings == null)
{
PrimitiveTypeCode typeCode = ConvertUtils.GetTypeCode(objectType);
bool isEnum;
PrimitiveTypeCode typeCode = ConvertUtils.GetTypeCode(objectType, out isEnum);
if (isEnum && Type == JTokenType.String)
{
Type enumType = objectType.IsEnum() ? objectType : Nullable.GetUnderlyingType(objectType);
try
{
return Enum.Parse(enumType, (string)this, true);
}
catch (Exception ex)
{
throw new ArgumentException("Could not convert '{0}' to {1}.".FormatWith(CultureInfo.InvariantCulture, (string)this, enumType.Name), ex);
}
}
switch (typeCode)
{
+1 -1
View File
@@ -872,7 +872,7 @@ namespace Newtonsoft.Json.Linq
return ReflectionUtils.IsNullable(binder.Type);
}
result = ConvertUtils.Convert(instance.Value, CultureInfo.InvariantCulture, binder.Type);
result = ConvertUtils.Convert(value, CultureInfo.InvariantCulture, binder.Type);
return true;
}
@@ -91,5 +91,5 @@ using System.Security;
// by using the '*' as shown below:
[assembly: AssemblyVersion("6.0.0.0")]
[assembly: AssemblyFileVersion("6.0.4.17603")]
[assembly: AssemblyFileVersion("6.0.4.17624")]
[assembly: CLSCompliant(true)]
@@ -23,7 +23,7 @@
// OTHER DEALINGS IN THE SOFTWARE.
#endregion
#if !(NET20 || NET35 || PORTABLE40)
#if !(NET20 || NET35)
using System;
using System.Collections.Generic;
#if NET20
@@ -403,10 +403,8 @@ namespace Newtonsoft.Json.Serialization
return DynamicReflectionDelegateFactory.Instance;
return LateBoundReflectionDelegateFactory.Instance;
#elif !(PORTABLE40)
return ExpressionReflectionDelegateFactory.Instance;
#else
return LateBoundReflectionDelegateFactory.Instance;
return ExpressionReflectionDelegateFactory.Instance;
#endif
}
}
+15 -6
View File
@@ -187,13 +187,25 @@ namespace Newtonsoft.Json.Utilities
#endif
public static PrimitiveTypeCode GetTypeCode(Type t)
{
bool isEnum;
return GetTypeCode(t, out isEnum);
}
public static PrimitiveTypeCode GetTypeCode(Type t, out bool isEnum)
{
PrimitiveTypeCode typeCode;
if (TypeCodeMap.TryGetValue(t, out typeCode))
{
isEnum = false;
return typeCode;
}
if (t.IsEnum())
{
isEnum = true;
return GetTypeCode(Enum.GetUnderlyingType(t));
}
// performance?
if (ReflectionUtils.IsNullableType(t))
@@ -202,18 +214,15 @@ namespace Newtonsoft.Json.Utilities
if (nonNullable.IsEnum())
{
Type nullableUnderlyingType = typeof(Nullable<>).MakeGenericType(Enum.GetUnderlyingType(nonNullable));
isEnum = true;
return GetTypeCode(nullableUnderlyingType);
}
}
isEnum = false;
return PrimitiveTypeCode.Object;
}
public static PrimitiveTypeCode GetTypeCode(object o)
{
return GetTypeCode(o.GetType());
}
#if !(NETFX_CORE || PORTABLE)
public static TypeInformation GetTypeInformation(IConvertible convertable)
{
@@ -623,7 +632,7 @@ namespace Newtonsoft.Json.Utilities
public static bool IsInteger(object value)
{
switch (GetTypeCode(value))
switch (GetTypeCode(value.GetType()))
{
case PrimitiveTypeCode.SByte:
case PrimitiveTypeCode.Byte:
@@ -23,7 +23,7 @@
// OTHER DEALINGS IN THE SOFTWARE.
#endregion
#if !(PORTABLE40 || NET20 || NET35)
#if !(NET20 || NET35)
using System;
using System.Linq.Expressions;
using System.Reflection;