diff options
author | JamesNK <james@newtonking.com> | 2010-09-11 12:06:53 +0400 |
---|---|---|
committer | JamesNK <james@newtonking.com> | 2010-09-11 12:06:53 +0400 |
commit | 43501484fbf58864fab17cc975afe60760113725 (patch) | |
tree | 6f41d0e6d7d3d341d5e702bd68075865e6d23085 /Src/Newtonsoft.Json | |
parent | 12a91cce9ee0f3675a8df44a9a204137c0b136b9 (diff) |
-Added .NET 3.5 build
-Added dynamic support to LINQ to JSON
-Added dynamic support to serializer
Diffstat (limited to 'Src/Newtonsoft.Json')
18 files changed, 1345 insertions, 31 deletions
diff --git a/Src/Newtonsoft.Json/Linq/JObject.cs b/Src/Newtonsoft.Json/Linq/JObject.cs index 079fee6..957e1f6 100644 --- a/Src/Newtonsoft.Json/Linq/JObject.cs +++ b/Src/Newtonsoft.Json/Linq/JObject.cs @@ -27,6 +27,10 @@ using System; using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
+#if !(NET35 || NET20 || SILVERLIGHT)
+using System.Dynamic;
+using System.Linq.Expressions;
+#endif
using System.Linq;
using System.IO;
using Newtonsoft.Json.Utilities;
@@ -650,5 +654,50 @@ namespace Newtonsoft.Json.Linq }
#endregion
#endif
+
+#if !(NET35 || NET20 || SILVERLIGHT)
+ /// <summary>
+ /// Returns the <see cref="T:System.Dynamic.DynamicMetaObject"/> responsible for binding operations performed on this object.
+ /// </summary>
+ /// <param name="parameter">The expression tree representation of the runtime value.</param>
+ /// <returns>
+ /// The <see cref="T:System.Dynamic.DynamicMetaObject"/> to bind this object.
+ /// </returns>
+ protected override DynamicMetaObject GetMetaObject(Expression parameter)
+ {
+ return new DynamicProxyMetaObject<JObject>(parameter, new JObjectDynamicProxy(this), true);
+ }
+
+ private class JObjectDynamicProxy : DynamicProxy<JObject>
+ {
+ public JObjectDynamicProxy(JObject value) : base(value)
+ {
+ }
+
+ public override bool TryGetMember(GetMemberBinder binder, out object result)
+ {
+ // result can be null
+ result = Value[binder.Name];
+ return true;
+ }
+
+ public override bool TrySetMember(SetMemberBinder binder, object value)
+ {
+ JToken v = value as JToken;
+
+ // this can throw an error if value isn't a valid for a JValue
+ if (v == null)
+ v = new JValue(value);
+
+ Value[binder.Name] = v;
+ return true;
+ }
+
+ public override IEnumerable<string> GetDynamicMemberNames()
+ {
+ return Value.Properties().Select(p => p.Name);
+ }
+ }
+#endif
}
}
\ No newline at end of file diff --git a/Src/Newtonsoft.Json/Linq/JToken.cs b/Src/Newtonsoft.Json/Linq/JToken.cs index ea88bbc..796d58b 100644 --- a/Src/Newtonsoft.Json/Linq/JToken.cs +++ b/Src/Newtonsoft.Json/Linq/JToken.cs @@ -25,6 +25,10 @@ using System;
using System.Collections.Generic;
+#if !(NET35 || NET20 || SILVERLIGHT)
+using System.Dynamic;
+using System.Linq.Expressions;
+#endif
using System.Linq;
using System.IO;
using Newtonsoft.Json.Utilities;
@@ -39,7 +43,10 @@ namespace Newtonsoft.Json.Linq /// Represents an abstract JSON token.
/// </summary>
public abstract class JToken : IJEnumerable<JToken>, IJsonLineInfo
- {
+#if !(NET35 || NET20 || SILVERLIGHT)
+ , IDynamicMetaObjectProvider
+#endif
+ {
private JContainer _parent;
internal JToken _next;
private static JTokenEqualityComparer _equalityComparer;
@@ -562,6 +569,35 @@ namespace Newtonsoft.Json.Linq }
/// <summary>
+ /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="System.Int16"/>.
+ /// </summary>
+ /// <param name="value">The value.</param>
+ /// <returns>The result of the conversion.</returns>
+ public static explicit operator short(JToken value)
+ {
+ JValue v = EnsureValue(value);
+ if (v == null || !ValidateInteger(v, false))
+ throw new ArgumentException("Can not convert {0} to Int16.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
+
+ return Convert.ToInt16(v.Value, CultureInfo.InvariantCulture);
+ }
+
+ /// <summary>
+ /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="System.UInt16"/>.
+ /// </summary>
+ /// <param name="value">The value.</param>
+ /// <returns>The result of the conversion.</returns>
+ [CLSCompliant(false)]
+ public static explicit operator ushort(JToken value)
+ {
+ JValue v = EnsureValue(value);
+ if (v == null || !ValidateInteger(v, false))
+ throw new ArgumentException("Can not convert {0} to UInt16.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
+
+ return Convert.ToUInt16(v.Value, CultureInfo.InvariantCulture);
+ }
+
+ /// <summary>
/// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="Nullable{Int32}"/>.
/// </summary>
/// <param name="value">The value.</param>
@@ -579,6 +615,41 @@ namespace Newtonsoft.Json.Linq }
/// <summary>
+ /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="Nullable{Int16}"/>.
+ /// </summary>
+ /// <param name="value">The value.</param>
+ /// <returns>The result of the conversion.</returns>
+ public static explicit operator short?(JToken value)
+ {
+ if (value == null)
+ return null;
+
+ JValue v = EnsureValue(value);
+ if (v == null || !ValidateInteger(v, true))
+ throw new ArgumentException("Can not convert {0} to Int16.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
+
+ return (v.Value != null) ? (short?)Convert.ToInt16(v.Value, CultureInfo.InvariantCulture) : null;
+ }
+
+ /// <summary>
+ /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="Nullable{UInt16}"/>.
+ /// </summary>
+ /// <param name="value">The value.</param>
+ /// <returns>The result of the conversion.</returns>
+ [CLSCompliant(false)]
+ public static explicit operator ushort?(JToken value)
+ {
+ if (value == null)
+ return null;
+
+ JValue v = EnsureValue(value);
+ if (v == null || !ValidateInteger(v, true))
+ throw new ArgumentException("Can not convert {0} to UInt16.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
+
+ return (v.Value != null) ? (ushort?)Convert.ToInt16(v.Value, CultureInfo.InvariantCulture) : null;
+ }
+
+ /// <summary>
/// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="System.DateTime"/>.
/// </summary>
/// <param name="value">The value.</param>
@@ -852,6 +923,17 @@ namespace Newtonsoft.Json.Linq }
/// <summary>
+ /// Performs an implicit conversion from <see cref="Int16"/> to <see cref="JToken"/>.
+ /// </summary>
+ /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
+ /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
+ [CLSCompliant(false)]
+ public static implicit operator JToken(short value)
+ {
+ return new JValue(value);
+ }
+
+ /// <summary>
/// Performs an implicit conversion from <see cref="UInt16"/> to <see cref="JToken"/>.
/// </summary>
/// <param name="value">The value to create a <see cref="JValue"/> from.</param>
@@ -923,6 +1005,17 @@ namespace Newtonsoft.Json.Linq }
/// <summary>
+ /// Performs an implicit conversion from <see cref="Nullable{Int16}"/> to <see cref="JToken"/>.
+ /// </summary>
+ /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
+ /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
+ [CLSCompliant(false)]
+ public static implicit operator JToken(short? value)
+ {
+ return new JValue(value);
+ }
+
+ /// <summary>
/// Performs an implicit conversion from <see cref="Nullable{UInt16}"/> to <see cref="JToken"/>.
/// </summary>
/// <param name="value">The value to create a <see cref="JValue"/> from.</param>
@@ -1179,5 +1272,31 @@ namespace Newtonsoft.Json.Linq JPath p = new JPath(path);
return p.Evaluate(this, errorWhenNoMatch);
}
+
+#if !(NET35 || NET20 || SILVERLIGHT)
+ /// <summary>
+ /// Returns the <see cref="T:System.Dynamic.DynamicMetaObject"/> responsible for binding operations performed on this object.
+ /// </summary>
+ /// <param name="parameter">The expression tree representation of the runtime value.</param>
+ /// <returns>
+ /// The <see cref="T:System.Dynamic.DynamicMetaObject"/> to bind this object.
+ /// </returns>
+ protected virtual DynamicMetaObject GetMetaObject(Expression parameter)
+ {
+ return new DynamicProxyMetaObject<JToken>(parameter, new DynamicProxy<JToken>(this), true);
+ }
+
+ /// <summary>
+ /// Returns the <see cref="T:System.Dynamic.DynamicMetaObject"/> responsible for binding operations performed on this object.
+ /// </summary>
+ /// <param name="parameter">The expression tree representation of the runtime value.</param>
+ /// <returns>
+ /// The <see cref="T:System.Dynamic.DynamicMetaObject"/> to bind this object.
+ /// </returns>
+ DynamicMetaObject IDynamicMetaObjectProvider.GetMetaObject(Expression parameter)
+ {
+ return GetMetaObject(parameter);
+ }
+#endif
}
}
\ No newline at end of file diff --git a/Src/Newtonsoft.Json/Newtonsoft.Json.Net35.csproj b/Src/Newtonsoft.Json/Newtonsoft.Json.Net35.csproj new file mode 100644 index 0000000..5edb4bc --- /dev/null +++ b/Src/Newtonsoft.Json/Newtonsoft.Json.Net35.csproj @@ -0,0 +1,265 @@ +<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.30729</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{A9AE40FF-1A21-414A-9FE7-3BE13644CC6D}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Newtonsoft.Json.Net35</RootNamespace>
+ <AssemblyName>Newtonsoft.Json.Net35</AssemblyName>
+ <SignAssembly>false</SignAssembly>
+ <AssemblyOriginatorKeyFile>
+ </AssemblyOriginatorKeyFile>
+ <SccProjectName>
+ </SccProjectName>
+ <SccLocalPath>
+ </SccLocalPath>
+ <SccAuxPath>
+ </SccAuxPath>
+ <SccProvider>
+ </SccProvider>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <OldToolsVersion>3.5</OldToolsVersion>
+ <UpgradeBackupLocation>
+ </UpgradeBackupLocation>
+ <IsWebBootstrapper>false</IsWebBootstrapper>
+ <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
+ <PublishUrl>publish\</PublishUrl>
+ <Install>true</Install>
+ <InstallFrom>Disk</InstallFrom>
+ <UpdateEnabled>false</UpdateEnabled>
+ <UpdateMode>Foreground</UpdateMode>
+ <UpdateInterval>7</UpdateInterval>
+ <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+ <UpdatePeriodically>false</UpdatePeriodically>
+ <UpdateRequired>false</UpdateRequired>
+ <MapFileExtensions>true</MapFileExtensions>
+ <ApplicationRevision>0</ApplicationRevision>
+ <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
+ <UseApplicationTrust>false</UseApplicationTrust>
+ <BootstrapperEnabled>true</BootstrapperEnabled>
+ <TargetFrameworkProfile>
+ </TargetFrameworkProfile>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\DotNet35\</OutputPath>
+ <DefineConstants>TRACE;DEBUG;CODE_ANALYSIS;NET35</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <DocumentationFile>bin\Debug\DotNet35\Newtonsoft.Json.Net35.xml</DocumentationFile>
+ <RunCodeAnalysis>true</RunCodeAnalysis>
+ <CodeAnalysisRules>
+ </CodeAnalysisRules>
+ <CodeAnalysisRuleSet>Newtonsoft.Json.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\DotNet35\</OutputPath>
+ <DefineConstants>TRACE;NET35</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <DocumentationFile>bin\Release\DotNet35\Newtonsoft.Json.Net35.xml</DocumentationFile>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Core">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Data" />
+ <Reference Include="System.Runtime.Serialization">
+ <RequiredTargetFramework>3.0</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Xml" />
+ <Reference Include="System.Xml.Linq">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Bson\BsonBinaryType.cs" />
+ <Compile Include="Bson\BsonBinaryWriter.cs" />
+ <Compile Include="Bson\BsonReader.cs" />
+ <Compile Include="Bson\BsonToken.cs" />
+ <Compile Include="Bson\BsonType.cs" />
+ <Compile Include="Bson\BsonWriter.cs" />
+ <Compile Include="Bson\BsonObjectId.cs" />
+ <Compile Include="Converters\BinaryConverter.cs" />
+ <Compile Include="Converters\DataSetConverter.cs" />
+ <Compile Include="Converters\DataTableConverter.cs" />
+ <Compile Include="Converters\CustomCreationConverter.cs" />
+ <Compile Include="Converters\DateTimeConverterBase.cs" />
+ <Compile Include="Converters\EntityKeyMemberConverter.cs" />
+ <Compile Include="Converters\KeyValuePairConverter.cs" />
+ <Compile Include="Converters\BsonObjectIdConverter.cs" />
+ <Compile Include="Converters\RegexConverter.cs" />
+ <Compile Include="Converters\StringEnumConverter.cs" />
+ <Compile Include="ConstructorHandling.cs" />
+ <Compile Include="Utilities\DynamicProxy.cs" />
+ <Compile Include="Linq\JPath.cs" />
+ <Compile Include="Linq\JRaw.cs" />
+ <Compile Include="Required.cs" />
+ <Compile Include="Serialization\JsonDynamicContract.cs" />
+ <Compile Include="Serialization\JsonFormatterConverter.cs" />
+ <Compile Include="Serialization\JsonISerializableContract.cs" />
+ <Compile Include="Serialization\JsonLinqContract.cs" />
+ <Compile Include="Serialization\JsonPrimitiveContract.cs" />
+ <Compile Include="Serialization\DynamicValueProvider.cs" />
+ <Compile Include="Serialization\ErrorEventArgs.cs" />
+ <Compile Include="Linq\ComponentModel\JPropertyDescriptor.cs" />
+ <Compile Include="Serialization\DefaultReferenceResolver.cs" />
+ <Compile Include="PreserveReferencesHandling.cs" />
+ <Compile Include="IJsonLineInfo.cs" />
+ <Compile Include="JsonArrayAttribute.cs" />
+ <Compile Include="JsonContainerAttribute.cs" />
+ <Compile Include="DefaultValueHandling.cs" />
+ <Compile Include="JsonConverterAttribute.cs" />
+ <Compile Include="JsonObjectAttribute.cs" />
+ <Compile Include="JsonSerializerSettings.cs" />
+ <Compile Include="JsonValidatingReader.cs" />
+ <Compile Include="Linq\IJEnumerable.cs" />
+ <Compile Include="Linq\JTokenEqualityComparer.cs" />
+ <Compile Include="MemberSerialization.cs" />
+ <Compile Include="ObjectCreationHandling.cs" />
+ <Compile Include="Converters\IsoDateTimeConverter.cs" />
+ <Compile Include="Converters\JavaScriptDateTimeConverter.cs" />
+ <Compile Include="Converters\JsonDateTimeSerializationMode.cs" />
+ <Compile Include="Converters\XmlNodeConverter.cs" />
+ <Compile Include="JsonTextReader.cs" />
+ <Compile Include="JsonPropertyAttribute.cs" />
+ <Compile Include="JsonIgnoreAttribute.cs" />
+ <Compile Include="JsonTextWriter.cs" />
+ <Compile Include="JsonWriterException.cs" />
+ <Compile Include="JsonReaderException.cs" />
+ <Compile Include="JsonConverter.cs" />
+ <Compile Include="JsonConverterCollection.cs" />
+ <Compile Include="JsonReader.cs" />
+ <Compile Include="JsonConvert.cs" />
+ <Compile Include="JsonSerializationException.cs" />
+ <Compile Include="JsonSerializer.cs" />
+ <Compile Include="Linq\Extensions.cs" />
+ <Compile Include="Linq\JConstructor.cs" />
+ <Compile Include="Linq\JContainer.cs" />
+ <Compile Include="Linq\JEnumerable.cs" />
+ <Compile Include="Linq\JObject.cs" />
+ <Compile Include="Linq\JArray.cs" />
+ <Compile Include="Linq\JTokenReader.cs" />
+ <Compile Include="Linq\JTokenWriter.cs" />
+ <Compile Include="Linq\JToken.cs" />
+ <Compile Include="Linq\JProperty.cs" />
+ <Compile Include="Linq\JTokenType.cs" />
+ <Compile Include="Linq\JValue.cs" />
+ <Compile Include="Schema\Extensions.cs" />
+ <Compile Include="Schema\JsonSchemaException.cs" />
+ <Compile Include="Schema\JsonSchemaModel.cs" />
+ <Compile Include="Schema\JsonSchemaModelBuilder.cs" />
+ <Compile Include="Schema\JsonSchemaNodeCollection.cs" />
+ <Compile Include="Schema\JsonSchemaNode.cs" />
+ <Compile Include="Schema\JsonSchemaResolver.cs" />
+ <Compile Include="Schema\JsonSchemaWriter.cs" />
+ <Compile Include="Schema\UndefinedSchemaIdHandling.cs" />
+ <Compile Include="Schema\ValidationEventArgs.cs" />
+ <Compile Include="Schema\ValidationEventHandler.cs" />
+ <Compile Include="Serialization\CamelCasePropertyNamesContractResolver.cs" />
+ <Compile Include="Serialization\DefaultContractResolver.cs" />
+ <Compile Include="Serialization\DefaultSerializationBinder.cs" />
+ <Compile Include="Serialization\ErrorContext.cs" />
+ <Compile Include="Serialization\IContractResolver.cs" />
+ <Compile Include="Serialization\IValueProvider.cs" />
+ <Compile Include="Serialization\JsonArrayContract.cs" />
+ <Compile Include="Serialization\JsonContract.cs" />
+ <Compile Include="Serialization\JsonDictionaryContract.cs" />
+ <Compile Include="Serialization\JsonProperty.cs" />
+ <Compile Include="Serialization\JsonPropertyCollection.cs" />
+ <Compile Include="MissingMemberHandling.cs" />
+ <Compile Include="NullValueHandling.cs" />
+ <Compile Include="ReferenceLoopHandling.cs" />
+ <Compile Include="Schema\JsonSchema.cs" />
+ <Compile Include="Schema\JsonSchemaBuilder.cs" />
+ <Compile Include="Schema\JsonSchemaConstants.cs" />
+ <Compile Include="Schema\JsonSchemaGenerator.cs" />
+ <Compile Include="Serialization\IReferenceResolver.cs" />
+ <Compile Include="Schema\JsonSchemaType.cs" />
+ <Compile Include="Serialization\JsonObjectContract.cs" />
+ <Compile Include="Serialization\JsonSerializerInternalBase.cs" />
+ <Compile Include="Serialization\JsonSerializerInternalReader.cs" />
+ <Compile Include="Serialization\JsonSerializerInternalWriter.cs" />
+ <Compile Include="Serialization\JsonSerializerProxy.cs" />
+ <Compile Include="Serialization\JsonStringContract.cs" />
+ <Compile Include="Serialization\JsonTypeReflector.cs" />
+ <Compile Include="Serialization\CachedAttributeGetter.cs" />
+ <Compile Include="Serialization\LateBoundMetadataTypeAttribute.cs" />
+ <Compile Include="Serialization\ReflectionValueProvider.cs" />
+ <Compile Include="Serialization\OnErrorAttribute.cs" />
+ <Compile Include="Utilities\Base64Encoder.cs" />
+ <Compile Include="Utilities\DynamicProxyMetaObject.cs" />
+ <Compile Include="Utilities\DynamicUtils.cs" />
+ <Compile Include="Utilities\DynamicWrapper.cs" />
+ <Compile Include="Utilities\DynamicReflectionDelegateFactory.cs" />
+ <Compile Include="Serialization\ObjectConstructor.cs" />
+ <Compile Include="Utilities\ILGeneratorExtensions.cs" />
+ <Compile Include="Utilities\ReflectionDelegateFactory.cs" />
+ <Compile Include="Utilities\LateBoundReflectionDelegateFactory.cs" />
+ <Compile Include="Utilities\MethodCall.cs" />
+ <Compile Include="Utilities\ThreadSafeStore.cs" />
+ <Compile Include="TypeNameHandling.cs" />
+ <Compile Include="Utilities\BidirectionalDictionary.cs" />
+ <Compile Include="Utilities\ConvertUtils.cs" />
+ <Compile Include="Utilities\CollectionWrapper.cs" />
+ <Compile Include="Utilities\DateTimeUtils.cs" />
+ <Compile Include="Utilities\DictionaryWrapper.cs" />
+ <Compile Include="Utilities\EnumUtils.cs" />
+ <Compile Include="Utilities\EnumValue.cs" />
+ <Compile Include="Utilities\EnumValues.cs" />
+ <Compile Include="Utilities\JavaScriptUtils.cs" />
+ <Compile Include="JsonToken.cs" />
+ <Compile Include="JsonWriter.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="Utilities\StringBuffer.cs" />
+ <Compile Include="Utilities\CollectionUtils.cs" />
+ <Compile Include="Utilities\ListWrapper.cs" />
+ <Compile Include="Utilities\MathUtils.cs" />
+ <Compile Include="Utilities\MiscellaneousUtils.cs" />
+ <Compile Include="Utilities\ReflectionUtils.cs" />
+ <Compile Include="Utilities\StringUtils.cs" />
+ <Compile Include="Utilities\ValidationUtils.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Framework.2.0">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 2.0 %28x86%29</ProductName>
+ <Install>true</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Framework.3.0">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.0 %28x86%29</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Framework.3.5">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5 SP1</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="Dynamic.snk" />
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+</Project>
\ No newline at end of file diff --git a/Src/Newtonsoft.Json/Newtonsoft.Json.Silverlight.csproj b/Src/Newtonsoft.Json/Newtonsoft.Json.Silverlight.csproj index e11fde6..b0dfbe6 100644 --- a/Src/Newtonsoft.Json/Newtonsoft.Json.Silverlight.csproj +++ b/Src/Newtonsoft.Json/Newtonsoft.Json.Silverlight.csproj @@ -165,6 +165,7 @@ <Compile Include="Serialization\JsonArrayContract.cs" />
<Compile Include="Serialization\JsonContract.cs" />
<Compile Include="Serialization\JsonDictionaryContract.cs" />
+ <Compile Include="Serialization\JsonDynamicContract.cs" />
<Compile Include="Serialization\JsonFormatterConverter.cs" />
<Compile Include="Serialization\JsonISerializableContract.cs" />
<Compile Include="Serialization\JsonLinqContract.cs" />
diff --git a/Src/Newtonsoft.Json/Newtonsoft.Json.csproj b/Src/Newtonsoft.Json/Newtonsoft.Json.csproj index 5d576f9..153a3e8 100644 --- a/Src/Newtonsoft.Json/Newtonsoft.Json.csproj +++ b/Src/Newtonsoft.Json/Newtonsoft.Json.csproj @@ -102,9 +102,11 @@ <Compile Include="Converters\RegexConverter.cs" />
<Compile Include="Converters\StringEnumConverter.cs" />
<Compile Include="ConstructorHandling.cs" />
+ <Compile Include="Utilities\DynamicProxy.cs" />
<Compile Include="Linq\JPath.cs" />
<Compile Include="Linq\JRaw.cs" />
<Compile Include="Required.cs" />
+ <Compile Include="Serialization\JsonDynamicContract.cs" />
<Compile Include="Serialization\JsonFormatterConverter.cs" />
<Compile Include="Serialization\JsonISerializableContract.cs" />
<Compile Include="Serialization\JsonLinqContract.cs" />
@@ -197,6 +199,8 @@ <Compile Include="Serialization\ReflectionValueProvider.cs" />
<Compile Include="Serialization\OnErrorAttribute.cs" />
<Compile Include="Utilities\Base64Encoder.cs" />
+ <Compile Include="Utilities\DynamicProxyMetaObject.cs" />
+ <Compile Include="Utilities\DynamicUtils.cs" />
<Compile Include="Utilities\DynamicWrapper.cs" />
<Compile Include="Utilities\DynamicReflectionDelegateFactory.cs" />
<Compile Include="Serialization\ObjectConstructor.cs" />
diff --git a/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs b/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs index 2c3fba4..df6333d 100644 --- a/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs +++ b/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs @@ -46,6 +46,8 @@ using System.Security; [assembly: InternalsVisibleTo("Newtonsoft.Json.Tests.Compact")]
#elif NET20
[assembly: InternalsVisibleTo("Newtonsoft.Json.Tests.Net20")]
+#elif NET35
+[assembly: InternalsVisibleTo("Newtonsoft.Json.Tests.Net35")]
#else
[assembly: InternalsVisibleTo("Newtonsoft.Json.Tests")]
#endif
diff --git a/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs b/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs index 6f5adf7..676acbd 100644 --- a/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs +++ b/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs @@ -27,6 +27,9 @@ using System; using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
+#if !(NET35 || NET20 || SILVERLIGHT)
+using System.Dynamic;
+#endif
using System.Globalization;
using System.Linq;
using System.Reflection;
@@ -270,7 +273,7 @@ namespace Newtonsoft.Json.Serialization InitializeContract(contract);
contract.MemberSerialization = JsonTypeReflector.GetObjectMemberSerialization(objectType);
- contract.Properties.AddRange(CreateProperties(contract));
+ contract.Properties.AddRange(CreateProperties(contract.UnderlyingType, contract.MemberSerialization));
if (contract.DefaultCreator == null || contract.DefaultCreatorNonPublic)
contract.ParametrizedConstructor = GetParametrizedConstructor(objectType);
@@ -443,6 +446,23 @@ namespace Newtonsoft.Json.Serialization }
#endif
+#if !(NET35 || NET20 || SILVERLIGHT)
+ /// <summary>
+ /// Creates a <see cref="JsonDynamicContract"/> for the given type.
+ /// </summary>
+ /// <param name="objectType">Type of the object.</param>
+ /// <returns>A <see cref="JsonDynamicContract"/> for the given type.</returns>
+ protected virtual JsonDynamicContract CreateDynamicContract(Type objectType)
+ {
+ JsonDynamicContract contract = new JsonDynamicContract(objectType);
+ InitializeContract(contract);
+
+ contract.Properties.AddRange(CreateProperties(objectType, MemberSerialization.OptOut));
+
+ return contract;
+ }
+#endif
+
/// <summary>
/// Creates a <see cref="JsonStringContract"/> for the given type.
/// </summary>
@@ -489,6 +509,11 @@ namespace Newtonsoft.Json.Serialization return CreateISerializableContract(objectType);
#endif
+#if !(NET35 || NET20 || SILVERLIGHT)
+ if (typeof(IDynamicMetaObjectProvider).IsAssignableFrom(objectType))
+ return CreateDynamicContract(objectType);
+#endif
+
return CreateObjectContract(objectType);
}
@@ -563,21 +588,22 @@ namespace Newtonsoft.Json.Serialization }
/// <summary>
- /// Creates properties for the given <see cref="JsonObjectContract"/>.
+ /// Creates properties for the given <see cref="JsonContract"/>.
/// </summary>
- /// <param name="contract">The contract to create properties for.</param>
- /// <returns>Properties for the given <see cref="JsonObjectContract"/>.</returns>
- protected virtual IList<JsonProperty> CreateProperties(JsonObjectContract contract)
+ /// <param name="type">The type to create properties for.</param>
+ /// /// <param name="memberSerialization">The member serialization mode for the type.</param>
+ /// <returns>Properties for the given <see cref="JsonContract"/>.</returns>
+ protected virtual IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
- List<MemberInfo> members = GetSerializableMembers(contract.UnderlyingType);
+ List<MemberInfo> members = GetSerializableMembers(type);
if (members == null)
throw new JsonSerializationException("Null collection of seralizable members returned.");
- JsonPropertyCollection properties = new JsonPropertyCollection(contract);
+ JsonPropertyCollection properties = new JsonPropertyCollection(type);
foreach (MemberInfo member in members)
{
- JsonProperty property = CreateProperty(contract, member);
+ JsonProperty property = CreateProperty(member, memberSerialization);
if (property != null)
properties.AddProperty(property);
@@ -604,10 +630,10 @@ namespace Newtonsoft.Json.Serialization /// <summary>
/// Creates a <see cref="JsonProperty"/> for the given <see cref="MemberInfo"/>.
/// </summary>
- /// <param name="contract">The member's declaring types <see cref="JsonObjectContract"/>.</param>
+ /// <param name="memberSerialization">The member's parent <see cref="MemberSerialization"/>.</param>
/// <param name="member">The member to create a <see cref="JsonProperty"/> for.</param>
/// <returns>A created <see cref="JsonProperty"/> for the given <see cref="MemberInfo"/>.</returns>
- protected virtual JsonProperty CreateProperty(JsonObjectContract contract, MemberInfo member)
+ protected virtual JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
JsonProperty property = new JsonProperty();
property.PropertyType = ReflectionUtils.GetMemberUnderlyingType(member);
@@ -652,7 +678,7 @@ namespace Newtonsoft.Json.Serialization property.Required = Required.Default;
property.Ignored = (hasIgnoreAttribute ||
- (contract.MemberSerialization == MemberSerialization.OptIn
+ (memberSerialization == MemberSerialization.OptIn
&& propertyAttribute == null
#if !PocketPC && !NET20
&& dataMemberAttribute == null
diff --git a/Src/Newtonsoft.Json/Serialization/JsonDynamicContract.cs b/Src/Newtonsoft.Json/Serialization/JsonDynamicContract.cs new file mode 100644 index 0000000..ade8c8a --- /dev/null +++ b/Src/Newtonsoft.Json/Serialization/JsonDynamicContract.cs @@ -0,0 +1,57 @@ +#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 || SILVERLIGHT)
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using Newtonsoft.Json.Utilities;
+using System.Collections;
+
+namespace Newtonsoft.Json.Serialization
+{
+ /// <summary>
+ /// Contract details for a <see cref="Type"/> used by the <see cref="JsonSerializer"/>.
+ /// </summary>
+ public class JsonDynamicContract : JsonContract
+ {
+ /// <summary>
+ /// Gets the object's properties.
+ /// </summary>
+ /// <value>The object's properties.</value>
+ public JsonPropertyCollection Properties { get; private set; }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="JsonDynamicContract"/> class.
+ /// </summary>
+ /// <param name="underlyingType">The underlying type for the contract.</param>
+ public JsonDynamicContract(Type underlyingType)
+ : base(underlyingType)
+ {
+ Properties = new JsonPropertyCollection(UnderlyingType);
+ }
+ }
+}
+#endif
\ No newline at end of file diff --git a/Src/Newtonsoft.Json/Serialization/JsonObjectContract.cs b/Src/Newtonsoft.Json/Serialization/JsonObjectContract.cs index bb07896..e52539f 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonObjectContract.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonObjectContract.cs @@ -58,7 +58,7 @@ namespace Newtonsoft.Json.Serialization public JsonObjectContract(Type underlyingType)
: base(underlyingType)
{
- Properties = new JsonPropertyCollection(this);
+ Properties = new JsonPropertyCollection(UnderlyingType);
}
}
}
\ No newline at end of file diff --git a/Src/Newtonsoft.Json/Serialization/JsonPropertyCollection.cs b/Src/Newtonsoft.Json/Serialization/JsonPropertyCollection.cs index 8bf17c9..e65fe13 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonPropertyCollection.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonPropertyCollection.cs @@ -37,16 +37,16 @@ namespace Newtonsoft.Json.Serialization /// </summary>
public class JsonPropertyCollection : KeyedCollection<string, JsonProperty>
{
- private readonly JsonObjectContract _contract;
+ private readonly Type _type;
/// <summary>
/// Initializes a new instance of the <see cref="JsonPropertyCollection"/> class.
/// </summary>
- /// <param name="contract">The contract.</param>
- public JsonPropertyCollection(JsonObjectContract contract)
+ /// <param name="type">The type.</param>
+ public JsonPropertyCollection(Type type)
{
- ValidationUtils.ArgumentNotNull(contract, "contract");
- _contract = contract;
+ ValidationUtils.ArgumentNotNull(type, "type");
+ _type = type;
}
/// <summary>
@@ -75,7 +75,7 @@ namespace Newtonsoft.Json.Serialization if (!existingProperty.Ignored)
throw new JsonSerializationException(
- "A member with the name '{0}' already exists on '{1}'. Use the JsonPropertyAttribute to specify another name.".FormatWith(CultureInfo.InvariantCulture, property.PropertyName, _contract.UnderlyingType));
+ "A member with the name '{0}' already exists on '{1}'. Use the JsonPropertyAttribute to specify another name.".FormatWith(CultureInfo.InvariantCulture, property.PropertyName, _type));
// remove ignored property so it can be replaced in collection
Remove(existingProperty);
diff --git a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs index c140241..4ca5afb 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs @@ -27,6 +27,9 @@ using System; using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
+#if !(NET35 || NET20 || SILVERLIGHT)
+using System.Dynamic;
+#endif
using System.Globalization;
using System.Linq;
using System.Reflection;
@@ -402,6 +405,14 @@ namespace Newtonsoft.Json.Serialization return CreateISerializable(reader, serializableContract, id);
}
#endif
+
+#if !(NET35 || NET20 || SILVERLIGHT)
+ JsonDynamicContract dynamicContract = contract as JsonDynamicContract;
+ if (dynamicContract != null)
+ {
+ return CreateDynamic(reader, dynamicContract, id);
+ }
+#endif
throw new JsonSerializationException("Cannot deserialize JSON object into type '{0}'.".FormatWith(CultureInfo.InvariantCulture, objectType));
}
@@ -717,6 +728,7 @@ namespace Newtonsoft.Json.Serialization if (id != null)
Serializer.ReferenceResolver.AddReference(id, createdObject);
+ // these are together because OnDeserializing takes an object but for an ISerializable the object is full created in the constructor
contract.InvokeOnDeserializing(createdObject, Serializer.Context);
contract.InvokeOnDeserialized(createdObject, Serializer.Context);
@@ -724,6 +736,64 @@ namespace Newtonsoft.Json.Serialization }
#endif
+#if !(NET35 || NET20 || SILVERLIGHT)
+ private object CreateDynamic(JsonReader reader, JsonDynamicContract contract, string id)
+ {
+ IDynamicMetaObjectProvider newObject = null;
+
+ if (contract.UnderlyingType.IsInterface || contract.UnderlyingType.IsAbstract)
+ throw new JsonSerializationException("Could not create an instance of type {0}. Type is an interface or abstract class and cannot be instantated.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));
+
+ if (contract.DefaultCreator != null &&
+ (!contract.DefaultCreatorNonPublic || Serializer.ConstructorHandling == ConstructorHandling.AllowNonPublicDefaultConstructor))
+ {
+ newObject = (IDynamicMetaObjectProvider)contract.DefaultCreator();
+ }
+
+ if (id != null)
+ Serializer.ReferenceResolver.AddReference(id, newObject);
+
+ contract.InvokeOnDeserializing(newObject, Serializer.Context);
+
+ bool exit = false;
+ do
+ {
+ switch (reader.TokenType)
+ {
+ case JsonToken.PropertyName:
+ string memberName = reader.Value.ToString();
+ if (!reader.Read())
+ throw new JsonSerializationException("Unexpected end when setting {0}'s value.".FormatWith(CultureInfo.InvariantCulture, memberName));
+
+ // first attempt to find a settable property, otherwise fall back to a dynamic set without type
+ JsonProperty property = contract.Properties.GetClosestMatchProperty(memberName);
+ if (property != null && property.Writable && !property.Ignored)
+ {
+ SetPropertyValue(property, reader, newObject);
+ }
+ else
+ {
+ object value = (JsonReader.IsPrimitiveToken(reader.TokenType))
+ ? reader.Value
+ : CreateObject(reader, typeof(IDynamicMetaObjectProvider), GetContractSafe(typeof(IDynamicMetaObjectProvider), null), null, null);
+
+ newObject.TrySetMember(memberName, value);
+ }
+ break;
+ case JsonToken.EndObject:
+ exit = true;
+ break;
+ default:
+ throw new JsonSerializationException("Unexpected token when deserializing object: " + reader.TokenType);
+ }
+ } while (!exit && reader.Read());
+
+ contract.InvokeOnDeserialized(newObject, Serializer.Context);
+
+ return newObject;
+ }
+#endif
+
private object CreateAndPopulateObject(JsonReader reader, JsonObjectContract contract, string id)
{
object newObject = null;
diff --git a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs index b2f6320..fa25fb0 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs @@ -27,6 +27,9 @@ using System; using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
+#if !(NET35 || NET20 || SILVERLIGHT)
+using System.Dynamic;
+#endif
using System.Globalization;
using System.Linq;
using System.Reflection;
@@ -132,6 +135,12 @@ namespace Newtonsoft.Json.Serialization SerializeISerializable(writer, (ISerializable) value, (JsonISerializableContract) valueContract);
}
#endif
+#if !(NET35 || NET20 || SILVERLIGHT)
+ else if (valueContract is JsonDynamicContract)
+ {
+ SerializeDynamic(writer, (IDynamicMetaObjectProvider) value, (JsonDynamicContract) valueContract);
+ }
+#endif
}
private bool ShouldWriteReference(object value, JsonProperty property, JsonContract contract)
@@ -463,18 +472,30 @@ namespace Newtonsoft.Json.Serialization }
#endif
- //private bool ShouldWriteTypeProperty(JsonProperty member, JsonContract contract, TypeNameHandling typeFlag)
- //{
- // if (HasFlag(((member != null) ? member.TypeNameHandling : null) ?? Serializer.TypeNameHandling, typeFlag))
- // return true;
+#if !(NET35 || NET20 || SILVERLIGHT)
+ private void SerializeDynamic(JsonWriter writer, IDynamicMetaObjectProvider value, JsonDynamicContract contract)
+ {
+ contract.InvokeOnSerializing(value, Serializer.Context);
+ SerializeStack.Add(value);
- // if ((((member != null) ? member.TypeNameHandling : null) ?? Serializer.TypeNameHandling) == TypeNameHandling.Auto)
+ writer.WriteStartObject();
- // || (member != null
- // && (member.TypeNameHandling ?? Serializer.TypeNameHandling) == TypeNameHandling.Auto
- // && contract.UnderlyingType != member.PropertyType)
- // )
- //}
+ foreach (string memberName in value.GetDynamicMemberNames())
+ {
+ object memberValue;
+ if (DynamicUtils.TryGetMember(value, memberName, out memberValue))
+ {
+ writer.WritePropertyName(memberName);
+ SerializeValue(writer, memberValue, GetContractSafe(memberValue), null, null);
+ }
+ }
+
+ writer.WriteEndObject();
+
+ SerializeStack.RemoveAt(SerializeStack.Count - 1);
+ contract.InvokeOnSerialized(value, Serializer.Context);
+ }
+#endif
private bool ShouldWriteType(TypeNameHandling typeNameHandlingFlag, JsonContract contract, JsonProperty member, JsonContract collectionValueContract)
{
diff --git a/Src/Newtonsoft.Json/Utilities/ConvertUtils.cs b/Src/Newtonsoft.Json/Utilities/ConvertUtils.cs index 6c9b8f2..2cc4f73 100644 --- a/Src/Newtonsoft.Json/Utilities/ConvertUtils.cs +++ b/Src/Newtonsoft.Json/Utilities/ConvertUtils.cs @@ -235,7 +235,7 @@ namespace Newtonsoft.Json.Utilities if (targetType == typeof (Uri))
return new Uri((string) initialValue);
if (targetType == typeof (TimeSpan))
-#if !NET20 && !SILVERLIGHT
+#if !(NET35 || NET20 || SILVERLIGHT)
return TimeSpan.Parse((string) initialValue, CultureInfo.InvariantCulture);
#else
return TimeSpan.Parse((string)initialValue);
diff --git a/Src/Newtonsoft.Json/Utilities/DynamicProxy.cs b/Src/Newtonsoft.Json/Utilities/DynamicProxy.cs new file mode 100644 index 0000000..cadbe93 --- /dev/null +++ b/Src/Newtonsoft.Json/Utilities/DynamicProxy.cs @@ -0,0 +1,94 @@ +#if !(NET35 || NET20 || SILVERLIGHT)
+using System;
+using System.Collections.Generic;
+using System.Dynamic;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Text;
+
+namespace Newtonsoft.Json.Utilities
+{
+ internal class DynamicProxy<T>
+ {
+ public T Value { get; private set; }
+
+ public DynamicProxy(T value)
+ {
+ Value = value;
+ }
+
+ public virtual IEnumerable<string> GetDynamicMemberNames()
+ {
+ return new string[0];
+ }
+
+ public virtual bool TryBinaryOperation(BinaryOperationBinder binder, object arg, out object result)
+ {
+ result = null;
+ return false;
+ }
+
+ public virtual bool TryConvert(ConvertBinder binder, out object result)
+ {
+ result = null;
+ return false;
+ }
+
+ public virtual bool TryCreateInstance(CreateInstanceBinder binder, object[] args, out object result)
+ {
+ result = null;
+ return false;
+ }
+
+ public virtual bool TryDeleteIndex(DeleteIndexBinder binder, object[] indexes)
+ {
+ return false;
+ }
+
+ public virtual bool TryDeleteMember(DeleteMemberBinder binder)
+ {
+ return false;
+ }
+
+ public virtual bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result)
+ {
+ result = null;
+ return false;
+ }
+
+ public virtual bool TryGetMember(GetMemberBinder binder, out object result)
+ {
+ result = null;
+ return false;
+ }
+
+ public virtual bool TryInvoke(InvokeBinder binder, object[] args, out object result)
+ {
+ result = null;
+ return false;
+ }
+
+ public virtual bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
+ {
+ result = null;
+ return false;
+ }
+
+ public virtual bool TrySetIndex(SetIndexBinder binder, object[] indexes, object value)
+ {
+ return false;
+ }
+
+ public virtual bool TrySetMember(SetMemberBinder binder, object value)
+ {
+ return false;
+ }
+
+ public virtual bool TryUnaryOperation(UnaryOperationBinder binder, out object result)
+ {
+ result = null;
+ return false;
+ }
+ }
+}
+#endif
\ No newline at end of file diff --git a/Src/Newtonsoft.Json/Utilities/DynamicProxyMetaObject.cs b/Src/Newtonsoft.Json/Utilities/DynamicProxyMetaObject.cs new file mode 100644 index 0000000..58ba434 --- /dev/null +++ b/Src/Newtonsoft.Json/Utilities/DynamicProxyMetaObject.cs @@ -0,0 +1,398 @@ +#if !(NET35 || NET20 || SILVERLIGHT)
+using System;
+using System.Collections.Generic;
+using System.Dynamic;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Reflection;
+
+namespace Newtonsoft.Json.Utilities
+{
+ internal sealed class DynamicProxyMetaObject<T> : DynamicMetaObject
+ {
+ private readonly DynamicProxy<T> _proxy;
+ private readonly bool _dontFallbackFirst;
+
+ internal DynamicProxyMetaObject(Expression expression, DynamicProxy<T> proxy, bool dontFallbackFirst)
+ : base(expression, BindingRestrictions.Empty, proxy.Value)
+ {
+ _proxy = proxy;
+ _dontFallbackFirst = dontFallbackFirst;
+ }
+
+ private new T Value { get { return (T)base.Value; } }
+
+ private bool IsOverridden(string method)
+ {
+ return _proxy.GetType().GetMember(method, MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance).Cast<MethodInfo>()
+ .Any(info =>
+ // check that the method overrides the original on DynamicObjectProxy
+ info.DeclaringType != typeof(DynamicProxy<T>) &&
+ info.GetBaseDefinition().DeclaringType == typeof(DynamicProxy<T>));
+ }
+
+ public override DynamicMetaObject BindGetMember(GetMemberBinder binder)
+ {
+ return IsOverridden("TryGetMember")
+ ? CallMethodWithResult("TryGetMember", binder, NoArgs, e => binder.FallbackGetMember(this, e))
+ : base.BindGetMember(binder);
+ }
+
+ public override DynamicMetaObject BindSetMember(SetMemberBinder binder, DynamicMetaObject value)
+ {
+ return IsOverridden("TrySetMember")
+ ? CallMethodReturnLast("TrySetMember", binder, GetArgs(value), e => binder.FallbackSetMember(this, value, e))
+ : base.BindSetMember(binder, value);
+ }
+
+ public override DynamicMetaObject BindDeleteMember(DeleteMemberBinder binder)
+ {
+ return IsOverridden("TryDeleteMember")
+ ? CallMethodNoResult("TryDeleteMember", binder, NoArgs, e => binder.FallbackDeleteMember(this, e))
+ : base.BindDeleteMember(binder);
+ }
+
+
+ public override DynamicMetaObject BindConvert(ConvertBinder binder)
+ {
+ return IsOverridden("TryConvert")
+ ? CallMethodWithResult("TryConvert", binder, NoArgs, e => binder.FallbackConvert(this, e))
+ : base.BindConvert(binder);
+ }
+
+ public override DynamicMetaObject BindInvokeMember(InvokeMemberBinder binder, DynamicMetaObject[] args)
+ {
+ if (!IsOverridden("TryInvokeMember"))
+ return base.BindInvokeMember(binder, args);
+
+ //
+ // Generate a tree like:
+ //
+ // {
+ // object result;
+ // TryInvokeMember(payload, out result)
+ // ? result
+ // : TryGetMember(payload, out result)
+ // ? FallbackInvoke(result)
+ // : fallbackResult
+ // }
+ //
+ // Then it calls FallbackInvokeMember with this tree as the
+ // "error", giving the language the option of using this
+ // tree or doing .NET binding.
+ //
+ Fallback fallback = e => binder.FallbackInvokeMember(this, args, e);
+
+ DynamicMetaObject call = BuildCallMethodWithResult(
+ "TryInvokeMember",
+ binder,
+ GetArgArray(args),
+ BuildCallMethodWithResult(
+ "TryGetMember",
+ new GetBinderAdapter(binder),
+ NoArgs,
+ fallback(null),
+ e => binder.FallbackInvoke(e, args, null)
+ ),
+ null
+ );
+
+ return _dontFallbackFirst ? call : fallback(call);
+ }
+
+
+ public override DynamicMetaObject BindCreateInstance(CreateInstanceBinder binder, DynamicMetaObject[] args)
+ {
+ return IsOverridden("TryCreateInstance")
+ ? CallMethodWithResult("TryCreateInstance", binder, GetArgArray(args), e => binder.FallbackCreateInstance(this, args, e))
+ : base.BindCreateInstance(binder, args);
+ }
+
+ public override DynamicMetaObject BindInvoke(InvokeBinder binder, DynamicMetaObject[] args)
+ {
+ return IsOverridden("TryInvoke")
+ ? CallMethodWithResult("TryInvoke", binder, GetArgArray(args), e => binder.FallbackInvoke(this, args, e))
+ : base.BindInvoke(binder, args);
+ }
+
+ public override DynamicMetaObject BindBinaryOperation(BinaryOperationBinder binder, DynamicMetaObject arg)
+ {
+ return IsOverridden("TryBinaryOperation")
+ ? CallMethodWithResult("TryBinaryOperation", binder, GetArgs(arg), e => binder.FallbackBinaryOperation(this, arg, e))
+ : base.BindBinaryOperation(binder, arg);
+ }
+
+ public override DynamicMetaObject BindUnaryOperation(UnaryOperationBinder binder)
+ {
+ return IsOverridden("TryUnaryOperation")
+ ? CallMethodWithResult("TryUnaryOperation", binder, NoArgs, e => binder.FallbackUnaryOperation(this, e))
+ : base.BindUnaryOperation(binder);
+ }
+
+ public override DynamicMetaObject BindGetIndex(GetIndexBinder binder, DynamicMetaObject[] indexes)
+ {
+ return IsOverridden("TryGetIndex")
+ ? CallMethodWithResult("TryGetIndex", binder, GetArgArray(indexes), e => binder.FallbackGetIndex(this, indexes, e))
+ : base.BindGetIndex(binder, indexes);
+ }
+
+ public override DynamicMetaObject BindSetIndex(SetIndexBinder binder, DynamicMetaObject[] indexes, DynamicMetaObject value)
+ {
+ return IsOverridden("TrySetIndex")
+ ? CallMethodReturnLast("TrySetIndex", binder, GetArgArray(indexes, value), e => binder.FallbackSetIndex(this, indexes, value, e))
+ : base.BindSetIndex(binder, indexes, value);
+ }
+
+ public override DynamicMetaObject BindDeleteIndex(DeleteIndexBinder binder, DynamicMetaObject[] indexes)
+ {
+ return IsOverridden("TryDeleteIndex")
+ ? CallMethodNoResult("TryDeleteIndex", binder, GetArgArray(indexes), e => binder.FallbackDeleteIndex(this, indexes, e))
+ : base.BindDeleteIndex(binder, indexes);
+ }
+
+ private delegate DynamicMetaObject Fallback(DynamicMetaObject errorSuggestion);
+
+ private readonly static Expression[] NoArgs = new Expression[0];
+
+ private static Expression[] GetArgs(params DynamicMetaObject[] args)
+ {
+ return args.Select(arg => Expression.Convert(arg.Expression, typeof(object))).ToArray();
+ }
+
+ private static Expression[] GetArgArray(DynamicMetaObject[] args)
+ {
+ return new[] { Expression.NewArrayInit(typeof(object), GetArgs(args)) };
+ }
+
+ private static Expression[] GetArgArray(DynamicMetaObject[] args, DynamicMetaObject value)
+ {
+ return new Expression[]
+ {
+ Expression.NewArrayInit(typeof(object), GetArgs(args)),
+ Expression.Convert(value.Expression, typeof(object))
+ };
+ }
+
+ private static ConstantExpression Constant(DynamicMetaObjectBinder binder)
+ {
+ Type t = binder.GetType();
+ while (!t.IsVisible)
+ t = t.BaseType;
+ return Expression.Constant(binder, t);
+ }
+
+ /// <summary>
+ /// Helper method for generating a MetaObject which calls a
+ /// specific method on Dynamic that returns a result
+ /// </summary>
+ private DynamicMetaObject CallMethodWithResult(string methodName, DynamicMetaObjectBinder binder, Expression[] args, Fallback fallback, Fallback fallbackInvoke = null)
+ {
+ //
+ // First, call fallback to do default binding
+ // This produces either an error or a call to a .NET member
+ //
+ DynamicMetaObject fallbackResult = fallback(null);
+
+ DynamicMetaObject callDynamic = BuildCallMethodWithResult(methodName, binder, args, fallbackResult, fallbackInvoke);
+
+ //
+ // Now, call fallback again using our new MO as the error
+ // When we do this, one of two things can happen:
+ // 1. Binding will succeed, and it will ignore our call to
+ // the dynamic method, OR
+ // 2. Binding will fail, and it will use the MO we created
+ // above.
+ //
+
+ return _dontFallbackFirst ? callDynamic : fallback(callDynamic);
+ }
+
+ private DynamicMetaObject BuildCallMethodWithResult(string methodName, DynamicMetaObjectBinder binder, Expression[] args, DynamicMetaObject fallbackResult, Fallback fallbackInvoke)
+ {
+ //
+ // Build a new expression like:
+ // {
+ // object result;
+ // TryGetMember(payload, out result) ? fallbackInvoke(result) : fallbackResult
+ // }
+ //
+ ParameterExpression result = Expression.Parameter(typeof(object), null);
+
+
+ Expression[] callArgs = new Expression[args.Length + 2];
+ Array.Copy(args, 0, callArgs, 1, args.Length);
+ callArgs[0] = Constant(binder);
+ callArgs[callArgs.Length - 1] = result;
+
+ DynamicMetaObject resultMO = new DynamicMetaObject(result, BindingRestrictions.Empty);
+
+ // Need to add a conversion if calling TryConvert
+ if (binder.ReturnType != typeof (object))
+ {
+ UnaryExpression convert = Expression.Convert(resultMO.Expression, binder.ReturnType);
+ // will always be a cast or unbox
+
+ resultMO = new DynamicMetaObject(convert, resultMO.Restrictions);
+ }
+
+ if (fallbackInvoke != null)
+ resultMO = fallbackInvoke(resultMO);
+
+ DynamicMetaObject callDynamic = new DynamicMetaObject(
+ Expression.Block(
+ new[] {result},
+ Expression.Condition(
+ Expression.Call(
+ Expression.Constant(_proxy),
+ typeof(DynamicProxy<T>).GetMethod(methodName),
+ callArgs
+ ),
+ resultMO.Expression,
+ fallbackResult.Expression,
+ binder.ReturnType
+ )
+ ),
+ GetRestrictions().Merge(resultMO.Restrictions).Merge(fallbackResult.Restrictions)
+ );
+
+ return callDynamic;
+ }
+
+ /// <summary>
+ /// Helper method for generating a MetaObject which calls a
+ /// specific method on Dynamic, but uses one of the arguments for
+ /// the result.
+ /// </summary>
+ private DynamicMetaObject CallMethodReturnLast(string methodName, DynamicMetaObjectBinder binder, Expression[] args, Fallback fallback)
+ {
+ //
+ // First, call fallback to do default binding
+ // This produces either an error or a call to a .NET member
+ //
+ DynamicMetaObject fallbackResult = fallback(null);
+
+ //
+ // Build a new expression like:
+ // {
+ // object result;
+ // TrySetMember(payload, result = value) ? result : fallbackResult
+ // }
+ //
+ ParameterExpression result = Expression.Parameter(typeof(object), null);
+ Expression[] callArgs = AddFirst(args, Constant(binder));
+ callArgs[args.Length] = Expression.Assign(result, callArgs[args.Length]);
+
+ DynamicMetaObject callDynamic = new DynamicMetaObject(
+ Expression.Block(
+ new[] { result },
+ Expression.Condition(
+ Expression.Call(
+ Expression.Constant(_proxy),
+ typeof(DynamicProxy<T>).GetMethod(methodName),
+ callArgs
+ ),
+ result,
+ fallbackResult.Expression,
+ typeof(object)
+ )
+ ),
+ GetRestrictions().Merge(fallbackResult.Restrictions)
+ );
+
+ //
+ // Now, call fallback again using our new MO as the error
+ // When we do this, one of two things can happen:
+ // 1. Binding will succeed, and it will ignore our call to
+ // the dynamic method, OR
+ // 2. Binding will fail, and it will use the MO we created
+ // above.
+ //
+ return _dontFallbackFirst ? callDynamic : fallback(callDynamic);
+ }
+
+ internal static TItem[] AddFirst<TItem>(IList<TItem> list, TItem item)
+ {
+ TItem[] res = new TItem[list.Count + 1];
+ res[0] = item;
+ list.CopyTo(res, 1);
+ return res;
+ }
+
+ /// <summary>
+ /// Helper method for generating a MetaObject which calls a
+ /// specific method on Dynamic, but uses one of the arguments for
+ /// the result.
+ /// </summary>
+ private DynamicMetaObject CallMethodNoResult(string methodName, DynamicMetaObjectBinder binder, Expression[] args, Fallback fallback)
+ {
+ //
+ // First, call fallback to do default binding
+ // This produces either an error or a call to a .NET member
+ //
+ DynamicMetaObject fallbackResult = fallback(null);
+
+ //
+ // Build a new expression like:
+ // if (TryDeleteMember(payload)) { } else { fallbackResult }
+ //
+ DynamicMetaObject callDynamic = new DynamicMetaObject(
+ Expression.Condition(
+ Expression.Call(
+ Expression.Constant(_proxy),
+ typeof(DynamicProxy<T>).GetMethod(methodName),
+ AddFirst(args, Constant(binder))
+ ),
+ Expression.Empty(),
+ fallbackResult.Expression,
+ typeof (void)
+ ),
+ GetRestrictions().Merge(fallbackResult.Restrictions)
+ );
+
+ //
+ // Now, call fallback again using our new MO as the error
+ // When we do this, one of two things can happen:
+ // 1. Binding will succeed, and it will ignore our call to
+ // the dynamic method, OR
+ // 2. Binding will fail, and it will use the MO we created
+ // above.
+ //
+ return _dontFallbackFirst ? callDynamic : fallback(callDynamic);
+ }
+
+ /// <summary>
+ /// Returns a Restrictions object which includes our current restrictions merged
+ /// with a restriction limiting our type
+ /// </summary>
+ private BindingRestrictions GetRestrictions()
+ {
+ // ReSharper disable CompareNonConstrainedGenericWithNull
+ return Value == null && HasValue // ReSharper restore CompareNonConstrainedGenericWithNull
+ ? BindingRestrictions.GetInstanceRestriction(Expression, null)
+ : BindingRestrictions.GetTypeRestriction(Expression, LimitType);
+ }
+
+ public override IEnumerable<string> GetDynamicMemberNames()
+ {
+ return _proxy.GetDynamicMemberNames();
+ }
+
+ // It is okay to throw NotSupported from this binder. This object
+ // is only used by DynamicObject.GetMember--it is not expected to
+ // (and cannot) implement binding semantics. It is just so the DO
+ // can use the Name and IgnoreCase properties.
+ private sealed class GetBinderAdapter : GetMemberBinder
+ {
+ internal GetBinderAdapter(InvokeMemberBinder binder) :
+ base(binder.Name, binder.IgnoreCase)
+ {
+ }
+
+ public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject errorSuggestion)
+ {
+ throw new NotSupportedException();
+ }
+ }
+ }
+}
+#endif
\ No newline at end of file diff --git a/Src/Newtonsoft.Json/Utilities/DynamicUtils.cs b/Src/Newtonsoft.Json/Utilities/DynamicUtils.cs new file mode 100644 index 0000000..75b9ac3 --- /dev/null +++ b/Src/Newtonsoft.Json/Utilities/DynamicUtils.cs @@ -0,0 +1,189 @@ +#if !(NET35 || NET20 || SILVERLIGHT)
+using System;
+using System.Collections.Generic;
+using System.Dynamic;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Text;
+using System.Globalization;
+
+namespace Newtonsoft.Json.Utilities
+{
+ internal static class DynamicUtils
+ {
+ internal static class BinderWrapper
+ {
+ private const string BinderTypeName = "Microsoft.CSharp.RuntimeBinder.Binder, Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
+ private const string CSharpArgumentInfoTypeName = "Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo, Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
+ private const string CSharpArgumentInfoFlagsTypeName = "Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfoFlags, Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
+ private const string CSharpBinderFlagsTypeName = "Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags, Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
+
+ private static object _getCSharpArgumentInfoArray;
+ private static object _setCSharpArgumentInfoArray;
+ private static MethodCall<object, object> _getMemberCall;
+ private static MethodCall<object, object> _setMemberCall;
+ private static bool _init;
+
+ private static void Init()
+ {
+ if (!_init)
+ {
+ Type binderType = Type.GetType(BinderTypeName, false);
+ if (binderType == null)
+ throw new Exception("Could not resolve type '{0}'. You may need to add a reference to Microsoft.CSharp.dll to work with dynamic types.".FormatWith(CultureInfo.InvariantCulture, BinderTypeName));
+
+ // None
+ _getCSharpArgumentInfoArray = CreateSharpArgumentInfoArray(0);
+ // None, Constant | UseCompileTimeType
+ _setCSharpArgumentInfoArray = CreateSharpArgumentInfoArray(0, 3);
+ CreateMemberCalls();
+
+ _init = true;
+ }
+ }
+
+ private static object CreateSharpArgumentInfoArray(params int[] values)
+ {
+ Type csharpArgumentInfoType = Type.GetType(CSharpArgumentInfoTypeName);
+ Type csharpArgumentInfoFlags = Type.GetType(CSharpArgumentInfoFlagsTypeName);
+
+ Array a = Array.CreateInstance(csharpArgumentInfoType, values.Length);
+
+ for (int i = 0; i < values.Length; i++)
+ {
+ MethodInfo createArgumentInfoMethod = csharpArgumentInfoType.GetMethod("Create", BindingFlags.Public | BindingFlags.Static, null, new[] { csharpArgumentInfoFlags, typeof(string) }, null);
+ object arg = createArgumentInfoMethod.Invoke(null, new object[] { 0, null });
+ a.SetValue(arg, i);
+ }
+
+ return a;
+ }
+
+ private static void CreateMemberCalls()
+ {
+ Type csharpArgumentInfoType = Type.GetType(CSharpArgumentInfoTypeName);
+ Type csharpBinderFlagsType = Type.GetType(CSharpBinderFlagsTypeName);
+ Type binderType = Type.GetType(BinderTypeName);
+
+ Type csharpArgumentInfoTypeEnumerableType = typeof(IEnumerable<>).MakeGenericType(csharpArgumentInfoType);
+
+ MethodInfo getMemberMethod = binderType.GetMethod("GetMember", BindingFlags.Public | BindingFlags.Static, null, new[] { csharpBinderFlagsType, typeof(string), typeof(Type), csharpArgumentInfoTypeEnumerableType }, null);
+ _getMemberCall = DynamicReflectionDelegateFactory.Instance.CreateMethodCall<object>(getMemberMethod);
+
+ MethodInfo setMemberMethod = binderType.GetMethod("SetMember", BindingFlags.Public | BindingFlags.Static, null, new[] { csharpBinderFlagsType, typeof(string), typeof(Type), csharpArgumentInfoTypeEnumerableType }, null);
+ _setMemberCall = DynamicReflectionDelegateFactory.Instance.CreateMethodCall<object>(setMemberMethod);
+ }
+
+ public static CallSiteBinder GetMember(string name, Type context)
+ {
+ Init();
+ return (CallSiteBinder)_getMemberCall(null, 0, name, context, _getCSharpArgumentInfoArray);
+ }
+
+ public static CallSiteBinder SetMember(string name, Type context)
+ {
+ Init();
+ return (CallSiteBinder)_setMemberCall(null, 0, name, context, _setCSharpArgumentInfoArray);
+ }
+ }
+
+ public static bool TryGetMember(this IDynamicMetaObjectProvider dynamicProvider, string name, out object value)
+ {
+ GetMemberBinder getMemberBinder = (GetMemberBinder) BinderWrapper.GetMember(name, typeof (DynamicUtils));
+
+ CallSite<Func<CallSite, object, object>> callSite = CallSite<Func<CallSite, object, object>>.Create(new NoThrowGetBinderMember(getMemberBinder));
+
+ object result = callSite.Target(callSite, dynamicProvider);
+
+ if (!ReferenceEquals(result, NoThrowExpressionVisitor.ErrorResult))
+ {
+ value = result;
+ return true;
+ }
+ else
+ {
+ value = null;
+ return false;
+ }
+ }
+
+ public static bool TrySetMember(this IDynamicMetaObjectProvider dynamicProvider, string name, object value)
+ {
+ SetMemberBinder binder = (SetMemberBinder) BinderWrapper.SetMember(name, value.GetType());
+
+ var setterSite = CallSite<Func<CallSite, object, object, object>>.Create(new NoThrowSetBinderMember(binder));
+
+ object result = setterSite.Target(setterSite, dynamicProvider, value);
+
+ return !ReferenceEquals(result, NoThrowExpressionVisitor.ErrorResult);
+ }
+
+ public static IEnumerable<string> GetDynamicMemberNames(this IDynamicMetaObjectProvider dynamicProvider)
+ {
+ DynamicMetaObject metaObject = dynamicProvider.GetMetaObject(Expression.Constant(dynamicProvider));
+ return metaObject.GetDynamicMemberNames();
+ }
+
+ internal class NoThrowGetBinderMember : GetMemberBinder
+ {
+ private readonly GetMemberBinder _innerBinder;
+
+ public NoThrowGetBinderMember(GetMemberBinder innerBinder)
+ : base(innerBinder.Name, innerBinder.IgnoreCase)
+ {
+ _innerBinder = innerBinder;
+ }
+
+ public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject errorSuggestion)
+ {
+ DynamicMetaObject retMetaObject = _innerBinder.Bind(target, new DynamicMetaObject[] { });
+
+ NoThrowExpressionVisitor noThrowVisitor = new NoThrowExpressionVisitor();
+ Expression resultExpression = noThrowVisitor.Visit(retMetaObject.Expression);
+
+ DynamicMetaObject finalMetaObject = new DynamicMetaObject(resultExpression, retMetaObject.Restrictions);
+ return finalMetaObject;
+ }
+ }
+
+ internal class NoThrowSetBinderMember : SetMemberBinder
+ {
+ private readonly SetMemberBinder _innerBinder;
+
+ public NoThrowSetBinderMember(SetMemberBinder innerBinder)
+ : base(innerBinder.Name, innerBinder.IgnoreCase)
+ {
+ _innerBinder = innerBinder;
+ }
+
+ public override DynamicMetaObject FallbackSetMember(DynamicMetaObject target, DynamicMetaObject value, DynamicMetaObject errorSuggestion)
+ {
+ DynamicMetaObject retMetaObject = _innerBinder.Bind(target, new DynamicMetaObject[] { value });
+
+ NoThrowExpressionVisitor noThrowVisitor = new NoThrowExpressionVisitor();
+ Expression resultExpression = noThrowVisitor.Visit(retMetaObject.Expression);
+
+ DynamicMetaObject finalMetaObject = new DynamicMetaObject(resultExpression, retMetaObject.Restrictions);
+ return finalMetaObject;
+ }
+ }
+
+
+ internal class NoThrowExpressionVisitor : ExpressionVisitor
+ {
+ internal static readonly object ErrorResult = new object();
+
+ protected override Expression VisitConditional(ConditionalExpression node)
+ {
+ // if the result of a test is to throw an error, rewrite to result an error result value
+ if (node.IfFalse.NodeType == ExpressionType.Throw)
+ return Expression.Condition(node.Test, node.IfTrue, Expression.Constant(ErrorResult));
+
+ return base.VisitConditional(node);
+ }
+ }
+ }
+}
+#endif
\ No newline at end of file diff --git a/Src/Newtonsoft.Json/Utilities/DynamicWrapper.cs b/Src/Newtonsoft.Json/Utilities/DynamicWrapper.cs index 6c80c65..8e88819 100644 --- a/Src/Newtonsoft.Json/Utilities/DynamicWrapper.cs +++ b/Src/Newtonsoft.Json/Utilities/DynamicWrapper.cs @@ -53,7 +53,14 @@ namespace Newtonsoft.Json.Utilities private static byte[] GetStrongKey()
{
- using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("Newtonsoft.Json.Dynamic.snk"))
+ string name;
+#if NET35
+ name = "Newtonsoft.Json.Net35.Dynamic.snk";
+#else
+ name = "Newtonsoft.Json.Dynamic.snk";
+#endif
+
+ using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(name))
{
if (stream == null)
throw new MissingManifestResourceException("Should have a Newtonsoft.Json.Dynamic.snk as an embedded resource.");
diff --git a/Src/Newtonsoft.Json/Utilities/LateBoundReflectionDelegateFactory.cs b/Src/Newtonsoft.Json/Utilities/LateBoundReflectionDelegateFactory.cs index e112ab4..11ae690 100644 --- a/Src/Newtonsoft.Json/Utilities/LateBoundReflectionDelegateFactory.cs +++ b/Src/Newtonsoft.Json/Utilities/LateBoundReflectionDelegateFactory.cs @@ -35,6 +35,8 @@ namespace Newtonsoft.Json.Utilities public override MethodCall<T, object> CreateMethodCall<T>(MethodBase method)
{
+ ValidationUtils.ArgumentNotNull(method, "method");
+
ConstructorInfo c = method as ConstructorInfo;
if (c != null)
return (o, a) => c.Invoke(a);
@@ -44,6 +46,8 @@ namespace Newtonsoft.Json.Utilities public override Func<T> CreateDefaultConstructor<T>(Type type)
{
+ ValidationUtils.ArgumentNotNull(type, "type");
+
if (type.IsValueType)
return () => (T)ReflectionUtils.CreateInstance(type);
@@ -54,21 +58,29 @@ namespace Newtonsoft.Json.Utilities public override Func<T, object> CreateGet<T>(PropertyInfo propertyInfo)
{
+ ValidationUtils.ArgumentNotNull(propertyInfo, "propertyInfo");
+
return o => propertyInfo.GetValue(o, null);
}
public override Func<T, object> CreateGet<T>(FieldInfo fieldInfo)
{
+ ValidationUtils.ArgumentNotNull(fieldInfo, "fieldInfo");
+
return o => fieldInfo.GetValue(o);
}
public override Action<T, object> CreateSet<T>(FieldInfo fieldInfo)
{
+ ValidationUtils.ArgumentNotNull(fieldInfo, "fieldInfo");
+
return (o, v) => fieldInfo.SetValue(o, v);
}
public override Action<T, object> CreateSet<T>(PropertyInfo propertyInfo)
{
+ ValidationUtils.ArgumentNotNull(propertyInfo, "propertyInfo");
+
return (o, v) => propertyInfo.SetValue(o, v, null);
}
}
|