-Fixed bug when converting certain XML with namespaces

-Add support for serializing F# lists, sets and maps
This commit is contained in:
James Newton-King
2014-03-09 17:46:36 +13:00
parent f6c74bdf3c
commit d5b71afc88
26 changed files with 9193 additions and 70 deletions
@@ -141,6 +141,24 @@ namespace Newtonsoft.Json.Tests.Converters
json = JsonConvert.SerializeXNode(doc1, Formatting.Indented, true);
Assert.AreEqual("null", json);
}
[Test]
public void SerializeAndDeserializeXmlWithNamespaceInChildrenAndNoValueInChildren()
{
var xmlString = @"<root>
<b xmlns='http://www.example.com/ns'/>
<c>AAA</c>
<test>adad</test>
</root>";
var xml = XElement.Parse(xmlString);
var json1 = JsonConvert.SerializeXNode(xml);
var xmlBack = JsonConvert.DeserializeObject<XElement>(json1);
var equals = XElement.DeepEquals(xmlBack, xml);
Assert.IsTrue(equals);
}
#endif
[Test]
@@ -50,6 +50,16 @@ namespace Newtonsoft.Json.Tests.Linq.JsonPath
[TestFixture]
public class JPathExecuteTests : TestFixtureBase
{
[Test]
public void EvaluateEmptyPropertyIndexer()
{
JObject o = new JObject(
new JProperty("", 1));
JToken t = o.SelectToken("['']");
Assert.AreEqual(1, (int)t);
}
[Test]
public void EvaluateEmptyString()
{
@@ -58,6 +68,19 @@ namespace Newtonsoft.Json.Tests.Linq.JsonPath
JToken t = o.SelectToken("");
Assert.AreEqual(o, t);
t = o.SelectToken("['']");
Assert.AreEqual(null, t);
}
[Test]
public void EvaluateEmptyStringWithMatchingEmptyProperty()
{
JObject o = new JObject(
new JProperty(" ", 1));
JToken t = o.SelectToken("[' ']");
Assert.AreEqual(1, (int)t);
}
[Test]
@@ -140,6 +140,7 @@
<Compile Include="Serialization\ContractResolverTests.cs" />
<Compile Include="Serialization\DefaultValueHandlingTests.cs" />
<Compile Include="Serialization\DynamicTests.cs" />
<Compile Include="Serialization\FSharpTests.cs" />
<Compile Include="Serialization\ImmutableCollectionsTests.cs" />
<Compile Include="Serialization\JsonPropertyCollectionTests.cs" />
<Compile Include="Serialization\NullValueHandlingTests.cs" />
@@ -66,6 +66,10 @@
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="FSharp.Core, Version=4.3.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\FSharp.Core.4.0.0\lib\FSharp.Core.dll</HintPath>
</Reference>
<Reference Include="Microsoft.CSharp" />
<Reference Include="nunit.framework, Version=2.6.2.12296, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
@@ -258,6 +262,7 @@
<Compile Include="Serialization\ContractResolverTests.cs" />
<Compile Include="Serialization\DefaultValueHandlingTests.cs" />
<Compile Include="Serialization\DynamicTests.cs" />
<Compile Include="Serialization\FSharpTests.cs" />
<Compile Include="Serialization\ImmutableCollectionsTests.cs" />
<Compile Include="Serialization\ReferenceLoopHandlingTests.cs" />
<Compile Include="Serialization\SpecialPropertyHandlingTests.cs" />
@@ -67,6 +67,10 @@
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="FSharp.Core, Version=4.3.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\FSharp.Core.4.0.0\lib\FSharp.Core.dll</HintPath>
</Reference>
<Reference Include="Microsoft.CSharp" />
<Reference Include="nunit.framework">
<HintPath>..\packages\NUnit.2.6.2\lib\nunit.framework.dll</HintPath>
@@ -142,6 +146,7 @@
<Compile Include="Serialization\ContractResolverTests.cs" />
<Compile Include="Serialization\DefaultValueHandlingTests.cs" />
<Compile Include="Serialization\DynamicTests.cs" />
<Compile Include="Serialization\FSharpTests.cs" />
<Compile Include="Serialization\ImmutableCollectionsTests.cs" />
<Compile Include="Serialization\ReferenceLoopHandlingTests.cs" />
<Compile Include="Serialization\SpecialPropertyHandlingTests.cs" />
@@ -67,6 +67,10 @@
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="FSharp.Core, Version=4.3.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\FSharp.Core.4.0.0\lib\FSharp.Core.dll</HintPath>
</Reference>
<Reference Include="Microsoft.CSharp" />
<Reference Include="nunit.framework, Version=2.6.2.12296, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
@@ -138,6 +142,7 @@
<Compile Include="Serialization\ContractResolverTests.cs" />
<Compile Include="Serialization\DefaultValueHandlingTests.cs" />
<Compile Include="Serialization\DynamicTests.cs" />
<Compile Include="Serialization\FSharpTests.cs" />
<Compile Include="Serialization\ReferenceLoopHandlingTests.cs" />
<Compile Include="Serialization\SpecialPropertyHandlingTests.cs" />
<Compile Include="Serialization\TraceWriterTests.cs" />
@@ -30,6 +30,10 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="FSharp.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\FSharp.Core.4.0.0\lib\FSharp.Core.dll</HintPath>
</Reference>
<Reference Include="nunit.framework, Version=2.6.2.12296, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\NUnit.2.6.2\lib\nunit.framework.dll</HintPath>
@@ -233,6 +237,7 @@
<Compile Include="Serialization\DefaultValueHandlingTests.cs" />
<Compile Include="Serialization\DynamicTests.cs" />
<Compile Include="Serialization\EntitiesSerializationTests.cs" />
<Compile Include="Serialization\FSharpTests.cs" />
<Compile Include="Serialization\ImmutableCollectionsTests.cs" />
<Compile Include="Serialization\JsonPropertyCollectionTests.cs" />
<Compile Include="Serialization\JsonSerializerTest.cs" />
@@ -75,4 +75,4 @@ using System.Security;
// by using the '*' as shown below:
[assembly: AssemblyVersion("6.0.0.0")]
[assembly: AssemblyFileVersion("6.0.1.17101")]
[assembly: AssemblyFileVersion("6.0.1.17109")]
@@ -0,0 +1,94 @@
#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
#if !(NET35 || NET20 || NETFX_CORE)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.FSharp.Collections;
using NUnit.Framework;
namespace Newtonsoft.Json.Tests.Serialization
{
[TestFixture]
public class FSharpTests : TestFixtureBase
{
[Test]
public void List()
{
FSharpList<int> l = ListModule.OfSeq(new List<int> {1,2,3});
string json = JsonConvert.SerializeObject(l, Formatting.Indented);
Assert.AreEqual(@"[
1,
2,
3
]", json);
FSharpList<int> l2 = JsonConvert.DeserializeObject<FSharpList<int>>(json);
Assert.AreEqual(l.Length, l2.Length);
CollectionAssert.AreEquivalent(l, l2);
}
[Test]
public void Set()
{
FSharpSet<int> l = SetModule.OfSeq(new List<int> { 1, 2, 3 });
string json = JsonConvert.SerializeObject(l, Formatting.Indented);
Assert.AreEqual(@"[
1,
2,
3
]", json);
FSharpSet<int> l2 = JsonConvert.DeserializeObject<FSharpSet<int>>(json);
Assert.AreEqual(l.Count, l2.Count);
CollectionAssert.AreEquivalent(l, l2);
}
[Test]
public void Map()
{
FSharpMap<string, int> m1 = MapModule.OfSeq(new List<Tuple<string, int>> { Tuple.Create("one", 1), Tuple.Create("II", 2), Tuple.Create("3", 3) });
string json = JsonConvert.SerializeObject(m1, Formatting.Indented);
FSharpMap<string, int> m2 = JsonConvert.DeserializeObject<FSharpMap<string, int>>(json);
Assert.AreEqual(m1.Count, m2.Count);
Assert.AreEqual(1, m2["one"]);
Assert.AreEqual(2, m2["II"]);
Assert.AreEqual(3, m2["3"]);
}
}
}
#endif
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="FSharp.Core" version="4.0.0" targetFramework="net45" />
<package id="Microsoft.Bcl.Immutable" version="1.0.27" targetFramework="net45" />
<package id="NUnit" version="2.6.2" targetFramework="net45" />
</packages>
@@ -23,6 +23,7 @@
// OTHER DEALINGS IN THE SOFTWARE.
#endregion
#if !(NET35 || NET20 || NETFX_CORE)
using System;
using System.Collections;
using System.Collections.Generic;
@@ -44,16 +45,6 @@ namespace Newtonsoft.Json.Converters
/// </summary>
public class DiscriminatedUnionConverter : JsonConverter
{
private static bool _initialized;
private static MethodCall<object, object> _isUnion;
private static MethodCall<object, object> _getUnionFields;
private static MethodCall<object, object> _getUnionCases;
private static MethodCall<object, object> _makeUnion;
private static Func<object, object> _getUnionCaseInfoName;
private static Func<object, object> _getUnionCaseInfo;
private static Func<object, object> _getUnionCaseFields;
private static MethodCall<object, object> _getUnionCaseInfoFields;
private const string CasePropertyName = "Case";
private const string FieldsPropertyName = "Fields";
@@ -69,10 +60,10 @@ namespace Newtonsoft.Json.Converters
Type t = value.GetType();
object result = _getUnionFields(null, value, t, null);
object info = _getUnionCaseInfo(result);
object fields = _getUnionCaseFields(result);
object caseName = _getUnionCaseInfoName(info);
object result = FSharpUtils.GetUnionFields(null, value, t, null);
object info = FSharpUtils.GetUnionCaseInfo(result);
object fields = FSharpUtils.GetUnionCaseFields(result);
object caseName = FSharpUtils.GetUnionCaseInfoName(info);
writer.WriteStartObject();
writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(CasePropertyName) : CasePropertyName);
@@ -95,7 +86,7 @@ namespace Newtonsoft.Json.Converters
if (reader.TokenType == JsonToken.Null)
return null;
IEnumerable cases = (IEnumerable)_getUnionCases(null, objectType, null);
IEnumerable cases = (IEnumerable)FSharpUtils.GetUnionCases(null, objectType, null);
ReadAndAssertProperty(reader, CasePropertyName);
ReadAndAssert(reader);
@@ -105,7 +96,7 @@ namespace Newtonsoft.Json.Converters
object matchingCaseInfo = null;
foreach (object c in cases)
{
if ((string)_getUnionCaseInfoName(c) == caseName)
if ((string)FSharpUtils.GetUnionCaseInfoName(c) == caseName)
{
matchingCaseInfo = c;
break;
@@ -121,7 +112,7 @@ namespace Newtonsoft.Json.Converters
// first value
ReadAndAssert(reader);
PropertyInfo[] fieldProperties = (PropertyInfo[])_getUnionCaseInfoFields(matchingCaseInfo);
PropertyInfo[] fieldProperties = (PropertyInfo[])FSharpUtils.GetUnionCaseInfoFields(matchingCaseInfo);
List<object> fieldValues = new List<object>();
foreach (PropertyInfo field in fieldProperties)
{
@@ -132,7 +123,7 @@ namespace Newtonsoft.Json.Converters
// end object
ReadAndAssert(reader);
return _makeUnion(null, matchingCaseInfo, fieldValues.ToArray(), null);
return FSharpUtils.MakeUnion(null, matchingCaseInfo, fieldValues.ToArray(), null);
}
/// <summary>
@@ -161,7 +152,7 @@ namespace Newtonsoft.Json.Converters
Type attributeType = attribute.GetType();
if (attributeType.Name == "CompilationMappingAttribute")
{
EnsureInitialized(attributeType);
FSharpUtils.EnsureInitialized(attributeType.Assembly());
isFSharpType = true;
break;
@@ -171,40 +162,7 @@ namespace Newtonsoft.Json.Converters
if (!isFSharpType)
return false;
return (bool)_isUnion(null, objectType, null);
}
private static void EnsureInitialized(Type attributeType)
{
if (!_initialized)
{
_initialized = true;
Assembly fsharpCoreAssembly = attributeType.Assembly();
Type fsharpType = fsharpCoreAssembly.GetType("Microsoft.FSharp.Reflection.FSharpType");
MethodInfo isUnionMethodInfo = fsharpType.GetMethod("IsUnion", BindingFlags.Public | BindingFlags.Static);
_isUnion = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall<object>(isUnionMethodInfo);
MethodInfo getUnionCasesMethodInfo = fsharpType.GetMethod("GetUnionCases", BindingFlags.Public | BindingFlags.Static);
_getUnionCases = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall<object>(getUnionCasesMethodInfo);
Type fsharpValue = fsharpCoreAssembly.GetType("Microsoft.FSharp.Reflection.FSharpValue");
MethodInfo getUnionFieldsMethodInfo = fsharpValue.GetMethod("GetUnionFields", BindingFlags.Public | BindingFlags.Static);
_getUnionFields = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall<object>(getUnionFieldsMethodInfo);
_getUnionCaseInfo = JsonTypeReflector.ReflectionDelegateFactory.CreateGet<object>(getUnionFieldsMethodInfo.ReturnType.GetProperty("Item1"));
_getUnionCaseFields = JsonTypeReflector.ReflectionDelegateFactory.CreateGet<object>(getUnionFieldsMethodInfo.ReturnType.GetProperty("Item2"));
MethodInfo makeUnionMethodInfo = fsharpValue.GetMethod("MakeUnion", BindingFlags.Public | BindingFlags.Static);
_makeUnion = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall<object>(makeUnionMethodInfo);
Type unionCaseInfo = fsharpCoreAssembly.GetType("Microsoft.FSharp.Reflection.UnionCaseInfo");
_getUnionCaseInfoName = JsonTypeReflector.ReflectionDelegateFactory.CreateGet<object>(unionCaseInfo.GetProperty("Name"));
_getUnionCaseInfoFields = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall<object>(unionCaseInfo.GetMethod("GetFields"));
}
return (bool)FSharpUtils.IsUnion(null, objectType, null);
}
private static void ReadAndAssertProperty(JsonReader reader, string propertyName)
@@ -221,4 +179,5 @@ namespace Newtonsoft.Json.Converters
throw new JsonSerializationException("Unexpected end.");
}
}
}
}
#endif
@@ -1234,8 +1234,9 @@ namespace Newtonsoft.Json.Converters
manager.PushScope();
DeserializeNode(reader, document, manager, element);
manager.PopScope();
manager.RemoveNamespace(string.Empty, manager.DefaultNamespace);
}
manager.RemoveNamespace(string.Empty, manager.DefaultNamespace);
}
}
}
@@ -241,6 +241,7 @@
<Compile Include="Utilities\DynamicReflectionDelegateFactory.cs" />
<Compile Include="Serialization\ObjectConstructor.cs" />
<Compile Include="Utilities\ExpressionReflectionDelegateFactory.cs" />
<Compile Include="Utilities\FSharpUtils.cs" />
<Compile Include="Utilities\ILGeneratorExtensions.cs" />
<Compile Include="Utilities\ImmutableCollectionsUtils.cs" />
<Compile Include="Utilities\LinqBridge.cs" />
@@ -241,6 +241,7 @@
<Compile Include="Utilities\DynamicReflectionDelegateFactory.cs" />
<Compile Include="Serialization\ObjectConstructor.cs" />
<Compile Include="Utilities\ExpressionReflectionDelegateFactory.cs" />
<Compile Include="Utilities\FSharpUtils.cs" />
<Compile Include="Utilities\ILGeneratorExtensions.cs" />
<Compile Include="Utilities\ImmutableCollectionsUtils.cs" />
<Compile Include="Utilities\LinqBridge.cs" />
@@ -213,6 +213,7 @@
<Compile Include="Utilities\EnumUtils.cs" />
<Compile Include="Utilities\EnumValue.cs" />
<Compile Include="Utilities\EnumValues.cs" />
<Compile Include="Utilities\FSharpUtils.cs" />
<Compile Include="Utilities\ILGeneratorExtensions.cs" />
<Compile Include="Utilities\ImmutableCollectionsUtils.cs" />
<Compile Include="Utilities\JavaScriptUtils.cs" />
@@ -218,6 +218,7 @@
<Compile Include="Utilities\EnumValue.cs" />
<Compile Include="Utilities\EnumValues.cs" />
<Compile Include="Utilities\ExpressionReflectionDelegateFactory.cs" />
<Compile Include="Utilities\FSharpUtils.cs" />
<Compile Include="Utilities\ILGeneratorExtensions.cs" />
<Compile Include="Utilities\JavaScriptUtils.cs" />
<Compile Include="Utilities\LateBoundReflectionDelegateFactory.cs" />
@@ -217,6 +217,7 @@
<Compile Include="Utilities\EnumValue.cs" />
<Compile Include="Utilities\EnumValues.cs" />
<Compile Include="Utilities\ExpressionReflectionDelegateFactory.cs" />
<Compile Include="Utilities\FSharpUtils.cs" />
<Compile Include="Utilities\ILGeneratorExtensions.cs" />
<Compile Include="Utilities\ImmutableCollectionsUtils.cs" />
<Compile Include="Utilities\JavaScriptUtils.cs" />
@@ -91,5 +91,5 @@ using System.Security;
// by using the '*' as shown below:
[assembly: AssemblyVersion("6.0.0.0")]
[assembly: AssemblyFileVersion("6.0.1.17101")]
[assembly: AssemblyFileVersion("6.0.1.17109")]
[assembly: CLSCompliant(true)]
@@ -113,11 +113,13 @@ namespace Newtonsoft.Json.Serialization
#endif
#if NETFX_CORE
new JsonValueConverter(),
#endif
#if !(NET35 || NET20 || NETFX_CORE)
new DiscriminatedUnionConverter(),
#endif
new KeyValuePairConverter(),
new BsonObjectIdConverter(),
new RegexConverter(),
new DiscriminatedUnionConverter()
new RegexConverter()
};
private static Dictionary<ResolverContractKey, JsonContract> _sharedContractCache;
@@ -721,29 +723,41 @@ namespace Newtonsoft.Json.Serialization
if (onSerializing != null)
{
#if NETFX_CORE
if (!t.IsGenericType() || (t.GetGenericTypeDefinition() != typeof(ConcurrentDictionary<,>)))
contract.OnSerializingCallbacks.AddRange(onSerializing);
#else
contract.OnSerializingCallbacks.AddRange(onSerializing);
#if !(NET35 || NET20 || NETFX_CORE)
if (t.Name != FSharpUtils.FSharpSetTypeName && t.Name != FSharpUtils.FSharpMapTypeName)
#endif
{
#if NETFX_CORE
if (!t.IsGenericType() || (t.GetGenericTypeDefinition() != typeof(ConcurrentDictionary<,>)))
contract.OnSerializingCallbacks.AddRange(onSerializing);
#else
contract.OnSerializingCallbacks.AddRange(onSerializing);
#endif
}
}
if (onSerialized != null)
contract.OnSerializedCallbacks.AddRange(onSerialized);
if (onDeserializing != null)
{
contract.OnDeserializingCallbacks.AddRange(onDeserializing);
}
if (onDeserialized != null)
{
// ConcurrentDictionary throws an error here so don't use its OnDeserialized - http://json.codeplex.com/discussions/257093
#if !(NET35 || NET20 || PORTABLE || PORTABLE40)
if (!t.IsGenericType() || (t.GetGenericTypeDefinition() != typeof(ConcurrentDictionary<,>)))
contract.OnDeserializedCallbacks.AddRange(onDeserialized);
#else
contract.OnDeserializedCallbacks.AddRange(onDeserialized);
#if !(NET35 || NET20 || NETFX_CORE)
if (t.Name != FSharpUtils.FSharpSetTypeName && t.Name != FSharpUtils.FSharpMapTypeName)
#endif
{
// ConcurrentDictionary throws an error here so don't use its OnDeserialized - http://json.codeplex.com/discussions/257093
#if !(NET35 || NET20 || PORTABLE || PORTABLE40)
if (!t.IsGenericType() || (t.GetGenericTypeDefinition() != typeof(ConcurrentDictionary<,>)))
contract.OnDeserializedCallbacks.AddRange(onDeserialized);
#else
contract.OnDeserializedCallbacks.AddRange(onDeserialized);
#endif
}
}
if (onError != null)
@@ -148,6 +148,14 @@ namespace Newtonsoft.Json.Serialization
ParametrizedConstructor = CollectionUtils.ResolveEnumableCollectionConstructor(underlyingType, CollectionItemType);
#if !(NET35 || NET20 || NETFX_CORE)
if (ParametrizedConstructor == null && underlyingType.Name == FSharpUtils.FSharpListTypeName)
{
FSharpUtils.EnsureInitialized(underlyingType.Assembly());
ParametrizedConstructor = FSharpUtils.CreateSeq(CollectionItemType);
}
#endif
if (underlyingType.IsGenericType() && underlyingType.GetGenericTypeDefinition() == typeof(IEnumerable<>))
{
_genericCollectionDefinitionType = tempCollectionType;
@@ -117,8 +117,18 @@ namespace Newtonsoft.Json.Serialization
}
if (keyType != null && valueType != null)
{
ParametrizedConstructor = CollectionUtils.ResolveEnumableCollectionConstructor(CreatedType, typeof(KeyValuePair<,>).MakeGenericType(keyType, valueType));
#if !(NET35 || NET20 || NETFX_CORE)
if (ParametrizedConstructor == null && underlyingType.Name == FSharpUtils.FSharpMapTypeName)
{
FSharpUtils.EnsureInitialized(underlyingType.Assembly());
ParametrizedConstructor = FSharpUtils.CreateMap(keyType, valueType);
}
#endif
}
ShouldCreateWrapper = !typeof(IDictionary).IsAssignableFrom(CreatedType);
DictionaryKeyType = keyType;
@@ -0,0 +1,144 @@
#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
#if !(NET35 || NET20 || NETFX_CORE)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using Newtonsoft.Json.Serialization;
namespace Newtonsoft.Json.Utilities
{
internal static class FSharpUtils
{
private static bool _initialized;
private static MethodInfo _ofSeq;
public static Assembly FSharpCoreAssembly { get; private set; }
public static MethodCall<object, object> IsUnion { get; private set; }
public static MethodCall<object, object> GetUnionFields { get; private set; }
public static MethodCall<object, object> GetUnionCases { get; private set; }
public static MethodCall<object, object> MakeUnion { get; private set; }
public static Func<object, object> GetUnionCaseInfoName { get; private set; }
public static Func<object, object> GetUnionCaseInfo { get; private set; }
public static Func<object, object> GetUnionCaseFields { get; private set; }
public static MethodCall<object, object> GetUnionCaseInfoFields { get; private set; }
public const string FSharpSetTypeName = "FSharpSet`1";
public const string FSharpListTypeName = "FSharpList`1";
public const string FSharpMapTypeName = "FSharpMap`2";
public static void EnsureInitialized(Assembly fsharpCoreAssembly)
{
if (!_initialized)
{
FSharpCoreAssembly = fsharpCoreAssembly;
Type fsharpType = fsharpCoreAssembly.GetType("Microsoft.FSharp.Reflection.FSharpType");
MethodInfo isUnionMethodInfo = fsharpType.GetMethod("IsUnion", BindingFlags.Public | BindingFlags.Static);
IsUnion = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall<object>(isUnionMethodInfo);
MethodInfo getUnionCasesMethodInfo = fsharpType.GetMethod("GetUnionCases", BindingFlags.Public | BindingFlags.Static);
GetUnionCases = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall<object>(getUnionCasesMethodInfo);
Type fsharpValue = fsharpCoreAssembly.GetType("Microsoft.FSharp.Reflection.FSharpValue");
MethodInfo getUnionFieldsMethodInfo = fsharpValue.GetMethod("GetUnionFields", BindingFlags.Public | BindingFlags.Static);
GetUnionFields = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall<object>(getUnionFieldsMethodInfo);
GetUnionCaseInfo = JsonTypeReflector.ReflectionDelegateFactory.CreateGet<object>(getUnionFieldsMethodInfo.ReturnType.GetProperty("Item1"));
GetUnionCaseFields = JsonTypeReflector.ReflectionDelegateFactory.CreateGet<object>(getUnionFieldsMethodInfo.ReturnType.GetProperty("Item2"));
MethodInfo makeUnionMethodInfo = fsharpValue.GetMethod("MakeUnion", BindingFlags.Public | BindingFlags.Static);
MakeUnion = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall<object>(makeUnionMethodInfo);
Type unionCaseInfo = fsharpCoreAssembly.GetType("Microsoft.FSharp.Reflection.UnionCaseInfo");
GetUnionCaseInfoName = JsonTypeReflector.ReflectionDelegateFactory.CreateGet<object>(unionCaseInfo.GetProperty("Name"));
GetUnionCaseInfoFields = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall<object>(unionCaseInfo.GetMethod("GetFields"));
Type listModule = fsharpCoreAssembly.GetType("Microsoft.FSharp.Collections.ListModule");
_ofSeq = listModule.GetMethod("OfSeq");
_initialized = true;
}
}
public static MethodInfo CreateSeq(Type t)
{
MethodInfo seqType = _ofSeq.MakeGenericMethod(t);
return seqType;
}
public static MethodInfo CreateMap(Type keyType, Type valueType)
{
Type t = typeof(FSharpMapCreator<,>).MakeGenericType(keyType, valueType);
MethodInfo initializeMethod = t.GetMethod("EnsureInitialized");
initializeMethod.Invoke(null, new object[] { FSharpCoreAssembly });
MethodInfo typedCreateMethod = t.GetMethod("CreateMapGeneric");
return typedCreateMethod;
}
}
internal static class FSharpMapCreator<TKey, TValue>
{
private static bool _initialized;
private static MethodCall<object, object> _createMap;
public static void EnsureInitialized(Assembly fsharpCoreAssembly)
{
if (!_initialized)
{
Type mapType = fsharpCoreAssembly.GetType("Microsoft.FSharp.Collections.FSharpMap`2");
Type genericMapType = mapType.MakeGenericType(typeof(TKey), typeof(TValue));
ConstructorInfo ctor = genericMapType.GetConstructor(new[] { typeof(IEnumerable<Tuple<TKey, TValue>>) });
_createMap = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall<object>(ctor);
_initialized = true;
}
}
public static object CreateMapGeneric(IEnumerable<KeyValuePair<TKey, TValue>> values)
{
IEnumerable<Tuple<TKey, TValue>> tupleValues = values.Select(kv => new Tuple<TKey, TValue>(kv.Key, kv.Value));
object map = _createMap(null, tupleValues);
return map;
}
}
}
#endif
Binary file not shown.
+16
View File
@@ -0,0 +1,16 @@
<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>FSharp.Core</id>
<version>4.0.0</version>
<title>FSharp.Core</title>
<authors>Microsoft</authors>
<owners>Microsoft</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>FSharp.Core.dll</description>
<releaseNotes>V 4.0.0</releaseNotes>
<copyright>Copyright 2012</copyright>
<language />
<tags>f#</tags>
</metadata>
</package>
Binary file not shown.
File diff suppressed because it is too large Load Diff