From 697e31444c1e238c64d90136abd2d22e45a5ca19 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Sun, 19 Oct 2014 23:11:58 +1300 Subject: [PATCH] -Changed MetadataTypeAttribute to use GetCustomeAttributes to support .NET 4.0 PCL --- Build/build.ps1 | 8 +--- .../Serialization/JsonSerializerTest.cs | 2 +- .../Serialization/JsonTypeReflector.cs | 41 ++++++++++--------- .../Utilities/ReflectionUtils.cs | 11 ----- 4 files changed, 24 insertions(+), 38 deletions(-) diff --git a/Build/build.ps1 b/Build/build.ps1 index 0c76fc1b..28ae4bfb 100644 --- a/Build/build.ps1 +++ b/Build/build.ps1 @@ -173,8 +173,7 @@ function CoreClrTests($build) try { Set-Location "$sourceDir\Newtonsoft.Json.Tests" - $logPath = "$workingDir\$name.txt" - k --configuration Release test -parallel none | Tee-Object -file $logPath + k --configuration Release test -parallel none | Tee-Object -file "$workingDir\$name.txt" } finally { @@ -196,10 +195,7 @@ function WinRTTests($build) Write-Host -ForegroundColor Green "Running MSTest tests " $name Write-Host - exec { &($testCmd) $outDir\$name\AppPackages\$($name)_1.0.0.0_AnyCPU_Debug_Test\$($name)_1.0.0.0_AnyCPU_Debug.appx /InIsolation /Logger:trx | Out-Default } "Error running $name tests" - - robocopy $baseDir\TestResults $workingDir /NP | Out-Default - del $baseDir\TestResults -Recurse -Force + exec { &($testCmd) $outDir\$name\AppPackages\$($name)_1.0.0.0_AnyCPU_Debug_Test\$($name)_1.0.0.0_AnyCPU_Debug.appx /InIsolation | Tee-Object -file "$workingDir\$name.txt" } "Error running $name tests" } function NUnitTests($build) diff --git a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs index caf65341..1493fc67 100644 --- a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs +++ b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs @@ -2527,7 +2527,7 @@ keyword such as type of business."" Assert.AreEqual("titleId", n.FidOrder[n.FidOrder.Count - 1]); } -#if !(NET20 || NETFX_CORE || ASPNETCORE50 || PORTABLE40) +#if !(NET20 || NETFX_CORE || ASPNETCORE50) [MetadataType(typeof(OptInClassMetadata))] public class OptInClass { diff --git a/Src/Newtonsoft.Json/Serialization/JsonTypeReflector.cs b/Src/Newtonsoft.Json/Serialization/JsonTypeReflector.cs index 6b694930..2ef1ac20 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonTypeReflector.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonTypeReflector.cs @@ -59,8 +59,9 @@ namespace Newtonsoft.Json.Serialization private static readonly ThreadSafeStore> JsonConverterCreatorCache = new ThreadSafeStore>(GetJsonConverterCreator); -#if !(NET20 || PORTABLE40 || NETFX_CORE) +#if !(NET20 || NETFX_CORE) private static readonly ThreadSafeStore AssociatedMetadataTypesCache = new ThreadSafeStore(GetAssociateMetadataTypeFromAttribute); + private static ReflectionObject _metadataTypeAttributeReflectionObject; #endif public static T GetCachedAttribute(object attributeProvider) where T : Attribute @@ -220,7 +221,7 @@ namespace Newtonsoft.Json.Serialization } #endif -#if !(NET20 || PORTABLE40 || NETFX_CORE) +#if !(NET20 || NETFX_CORE) private static Type GetAssociatedMetadataType(Type type) { return AssociatedMetadataTypesCache.Get(type); @@ -228,26 +229,26 @@ namespace Newtonsoft.Json.Serialization private static Type GetAssociateMetadataTypeFromAttribute(Type type) { - IList customAttributes = ReflectionUtils.GetCustomAttributeData(type); - - foreach (CustomAttributeData customAttributeData in customAttributes) - { - Type attributeType; - -#if (NET20 || NET35 || NET40) - attributeType = customAttributeData.Constructor.DeclaringType; + object[] customAttributes; +#if !PORTABLE + customAttributes = type.GetCustomAttributes(false); #else - attributeType = customAttributeData.AttributeType; + customAttributes = type.GetTypeInfo().GetCustomAttributes(false).Cast().ToArray(); #endif - if (attributeType != null - && string.Equals(attributeType.Name, "MetadataTypeAttribute", StringComparison.Ordinal) - && attributeType.Assembly().GetName().Name == "System.ComponentModel.DataAnnotations") - { - // MetadataTypeAttribute constructor takes one argument, the type we're looking for - CustomAttributeTypedArgument o = customAttributeData.ConstructorArguments[0]; + foreach (var attribute in customAttributes) + { + Type attributeType = attribute.GetType(); - return (Type)o.Value; + if (string.Equals(attributeType.Name, "MetadataTypeAttribute", StringComparison.Ordinal) + && attributeType.Assembly().FullName.StartsWith("System.ComponentModel.DataAnnotations", StringComparison.Ordinal)) + { + const string metadataClassTypeName = "MetadataClassType"; + + if (_metadataTypeAttributeReflectionObject == null) + _metadataTypeAttributeReflectionObject = ReflectionObject.Create(attributeType, metadataClassTypeName); + + return (Type)_metadataTypeAttributeReflectionObject.GetValue(attribute, metadataClassTypeName); } } @@ -259,7 +260,7 @@ namespace Newtonsoft.Json.Serialization { T attribute; -#if !(NET20 || PORTABLE40 || NETFX_CORE) +#if !(NET20 || NETFX_CORE) Type metadataType = GetAssociatedMetadataType(type); if (metadataType != null) { @@ -287,7 +288,7 @@ namespace Newtonsoft.Json.Serialization { T attribute; -#if !(NET20 || PORTABLE40 || NETFX_CORE) +#if !(NET20 || NETFX_CORE) Type metadataType = GetAssociatedMetadataType(memberInfo.DeclaringType); if (metadataType != null) { diff --git a/Src/Newtonsoft.Json/Utilities/ReflectionUtils.cs b/Src/Newtonsoft.Json/Utilities/ReflectionUtils.cs index d0bd4366..ca32ebb5 100644 --- a/Src/Newtonsoft.Json/Utilities/ReflectionUtils.cs +++ b/Src/Newtonsoft.Json/Utilities/ReflectionUtils.cs @@ -732,17 +732,6 @@ namespace Newtonsoft.Json.Utilities } #endif -#if !PORTABLE40 - public static IList GetCustomAttributeData(Type t) - { -#if !(NETFX_CORE || ASPNETCORE50 || PORTABLE) - return CustomAttributeData.GetCustomAttributes(t); -#else - return t.GetTypeInfo().CustomAttributes.ToList(); -#endif - } -#endif - public static void SplitFullyQualifiedTypeName(string fullyQualifiedTypeName, out string typeName, out string assemblyName) { int? assemblyDelimiterIndex = GetAssemblyDelimiterIndex(fullyQualifiedTypeName);