Imported Upstream version 3.6.0

Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
This commit is contained in:
Jo Shields
2014-08-13 10:39:27 +01:00
commit a575963da9
50588 changed files with 8155799 additions and 0 deletions

View File

@@ -0,0 +1,42 @@
//
// AssemblyInfo.cs
//
// Authors:
// Marek Safar (marek.safar@gmail.com)
//
// Copyright (C) 2007 Novell, Inc (http://www.novell.com)
//
// 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.
//
using System;
using System.Reflection;
using System.Resources;
using System.Security;
using System.Security.Permissions;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about the System.Json assembly
[assembly: AssemblyDefaultAlias ("System.Json.Microsoft.dll")]
[assembly: AssemblyInformationalVersion (Consts.FxFileVersion)]

View File

@@ -0,0 +1,16 @@
2010-03-10 Atsushi Enomoto <atsushi@ximian.com>
* AssemblyInfo.cs : use the same pub key in 2.0 (dummy), to ease
testing locally.
2008-05-07 Sebastien Pouliot <sebastien@ximian.com>
* AssemblyInfo.cs: Remove AssemblyDelaySign(true) since it's
not always needed and can be controlled from the Makefile.
Adjust public key for System.Windows (InternalsVisibleTo)
2008-04-13 Jb Evain <jbevain@novell.com>
* AssemblyInfo.cs: agmono is renamed to Mono.Moonlight.
Merged from the Moonlight 2 branch.

View File

@@ -0,0 +1,29 @@
2010-04-01 Miguel de Icaza <miguel@novell.com>
* JsonValue.cs: We need to use Convert.ToXXXX for numbers as we
always end up reporting the value JsonType.Number regardless of
the underlying storage (int, long or decimal). The parser
picks the best storage suitable for the data, and can end up using
"ints" for values that sometimes use longs.
This causes problems when derefercing the data for example, if you
have an int and try to get it out as a long you end up with an
invalid cast exception.
2010-03-10 Atsushi Enomoto <atsushi@ximian.com>
* System.Json.dll.sources : remove JsonReader.cs.
2010-03-10 Atsushi Enomoto <atsushi@ximian.com>
* Makefile : reference System.Xml and System.ServiceModel.Web (for
moonlight compatibility).
2009-08-13 Atsushi Enomoto <atsushi@ximian.com>
* Makefile : update profile check.
2008-06-10 Atsushi Enomoto <atsushi@ximian.com>
* System.Json.dll.sources, Makefile : initial checkin.

View File

@@ -0,0 +1,34 @@
thisdir = class/System.Json.Microsoft
SUBDIRS =
include ../../build/rules.make
System.Json.Properties.Resources.resources: System.Json/Properties/Resources.resx
$(RESGEN) "$<" "$@"
LIBRARY = System.Json.Microsoft.dll
LIB_MCS_FLAGS = /d:ASPNETMVC -keyfile:../winfx.pub -delaysign \
/r:System.dll \
/r:System.Xml.dll \
/r:System.Core.dll \
/r:System.Runtime.Serialization.dll \
/resource:System.Json.Properties.Resources.resources
EXTRA_DISTFILES = System.Json/Properties/Resources.resx
ifeq (4, $(FRAMEWORK_VERSION_MAJOR))
LIB_MCS_FLAGS += /r:Microsoft.CSharp.dll -d:FEATURE_DYNAMIC
endif
ifeq (monodroid, $(PROFILE))
LIB_MCS_FLAGS += -d:FEATURE_DYNAMIC
endif
ifeq (xammac, $(PROFILE))
LIB_MCS_FLAGS += -d:FEATURE_DYNAMIC
endif
TEST_MCS_FLAGS = $(LIB_MCS_FLAGS)
include ../../build/library.make
$(the_lib): System.Json.Properties.Resources.resources

View File

@@ -0,0 +1,22 @@
../../build/common/Consts.cs
Assembly/AssemblyInfo.cs
../../../external/aspnetwebstack/src/RS.cs
../../../external/aspnetwebstack/src/CommonAssemblyInfo.cs
../../../external/aspnetwebstack/src/TransparentCommonAssemblyInfo.cs
System.Json/Properties/AssemblyInfo.cs
System.Json/Extensions/JsonValueExtensions.cs
System.Json/GlobalSuppressions.cs
System.Json/JXmlToJsonValueConverter.cs
System.Json/JsonArray.cs
System.Json/JsonObject.cs
System.Json/JsonPrimitive.cs
System.Json/JsonType.cs
System.Json/JsonValue.cs
System.Json/JsonValueChange.cs
System.Json/JsonValueChangeEventArgs.cs
System.Json/JsonValueDynamicMetaObject.cs
System.Json/JsonValueLinqExtensions.cs
System.Json/NGenWrapper.cs
System.Json/Properties/Resources.Designer.cs

View File

@@ -0,0 +1 @@
System.Json/JsonValueTest.cs

View File

@@ -0,0 +1,383 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
#if FEATURE_DYNAMIC
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Dynamic;
using System.IO;
using System.Json;
using System.Linq.Expressions;
namespace System.Runtime.Serialization.Json
{
/// <summary>
/// This class extends the functionality of the <see cref="JsonValue"/> type.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
public static class JsonValueExtensions
{
/// <summary>
/// Creates a <see cref="System.Json.JsonValue"/> object based on an arbitrary CLR object.
/// </summary>
/// <param name="value">The object to be converted to <see cref="System.Json.JsonValue"/>.</param>
/// <returns>The <see cref="System.Json.JsonValue"/> which represents the given object.</returns>
/// <remarks>The conversion is done through the <see cref="System.Runtime.Serialization.Json.DataContractJsonSerializer"/>;
/// the object is first serialized into JSON using the serializer, then parsed into a <see cref="System.Json.JsonValue"/>
/// object.</remarks>
public static JsonValue CreateFrom(object value)
{
JsonValue jsonValue = null;
if (value != null)
{
jsonValue = value as JsonValue;
if (jsonValue == null)
{
jsonValue = JsonValueExtensions.CreatePrimitive(value);
if (jsonValue == null)
{
jsonValue = JsonValueExtensions.CreateFromDynamic(value);
if (jsonValue == null)
{
jsonValue = JsonValueExtensions.CreateFromComplex(value);
}
}
}
}
return jsonValue;
}
/// <summary>
/// Attempts to convert this <see cref="System.Json.JsonValue"/> instance into the type T.
/// </summary>
/// <typeparam name="T">The type to which the conversion is being performed.</typeparam>
/// <param name="jsonValue">The <see cref="JsonValue"/> instance this method extension is to be applied to.</param>
/// <param name="valueOfT">An instance of T initialized with this instance, or the default
/// value of T, if the conversion cannot be performed.</param>
/// <returns>true if this <see cref="System.Json.JsonValue"/> instance can be read as type T; otherwise, false.</returns>
public static bool TryReadAsType<T>(this JsonValue jsonValue, out T valueOfT)
{
if (jsonValue == null)
{
throw new ArgumentNullException("jsonValue");
}
object value;
if (JsonValueExtensions.TryReadAsType(jsonValue, typeof(T), out value))
{
valueOfT = (T)value;
return true;
}
valueOfT = default(T);
return false;
}
/// <summary>
/// Attempts to convert this <see cref="System.Json.JsonValue"/> instance into the type T.
/// </summary>
/// <typeparam name="T">The type to which the conversion is being performed.</typeparam>
/// <param name="jsonValue">The <see cref="JsonValue"/> instance this method extension is to be applied to.</param>
/// <returns>An instance of T initialized with the <see cref="System.Json.JsonValue"/> value
/// specified if the conversion.</returns>
/// <exception cref="System.NotSupportedException">If this <see cref="System.Json.JsonValue"/> value cannot be
/// converted into the type T.</exception>
[SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter",
Justification = "The generic parameter is used to specify the output type")]
public static T ReadAsType<T>(this JsonValue jsonValue)
{
if (jsonValue == null)
{
throw new ArgumentNullException("jsonValue");
}
return (T)JsonValueExtensions.ReadAsType(jsonValue, typeof(T));
}
/// <summary>
/// Attempts to convert this <see cref="System.Json.JsonValue"/> instance into the type T, returning a fallback value
/// if the conversion fails.
/// </summary>
/// <typeparam name="T">The type to which the conversion is being performed.</typeparam>
/// <param name="jsonValue">The <see cref="JsonValue"/> instance this method extension is to be applied to.</param>
/// <param name="fallback">A fallback value to be retuned in case the conversion cannot be performed.</param>
/// <returns>An instance of T initialized with the <see cref="System.Json.JsonValue"/> value
/// specified if the conversion succeeds or the specified fallback value if it fails.</returns>
public static T ReadAsType<T>(this JsonValue jsonValue, T fallback)
{
if (jsonValue == null)
{
throw new ArgumentNullException("jsonValue");
}
T outVal;
if (JsonValueExtensions.TryReadAsType<T>(jsonValue, out outVal))
{
return outVal;
}
return fallback;
}
/// <summary>
/// Attempts to convert this <see cref="System.Json.JsonValue"/> instance into an instance of the specified type.
/// </summary>
/// <param name="jsonValue">The <see cref="JsonValue"/> instance this method extension is to be applied to.</param>
/// <param name="type">The type to which the conversion is being performed.</param>
/// <returns>An object instance initialized with the <see cref="System.Json.JsonValue"/> value
/// specified if the conversion.</returns>
/// <exception cref="System.NotSupportedException">If this <see cref="System.Json.JsonValue"/> value cannot be
/// converted into the type T.</exception>
public static object ReadAsType(this JsonValue jsonValue, Type type)
{
if (jsonValue == null)
{
throw new ArgumentNullException("jsonValue");
}
if (type == null)
{
throw new ArgumentNullException("type");
}
object result;
if (JsonValueExtensions.TryReadAsType(jsonValue, type, out result))
{
return result;
}
throw new NotSupportedException(RS.Format(System.Json.Properties.Resources.CannotReadAsType, jsonValue.GetType().FullName, type.FullName));
}
/// <summary>
/// Attempts to convert this <see cref="System.Json.JsonValue"/> instance into an instance of the specified type.
/// </summary>
/// <param name="jsonValue">The <see cref="JsonValue"/> instance this method extension is to be applied to.</param>
/// <param name="type">The type to which the conversion is being performed.</param>
/// <param name="value">An object to be initialized with this instance or null if the conversion cannot be performed.</param>
/// <returns>true if this <see cref="System.Json.JsonValue"/> instance can be read as the specified type; otherwise, false.</returns>
[SuppressMessage("Microsoft.Design", "CA1007:UseGenericsWhereAppropriate",
Justification = "This is the non-generic version of the method.")]
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Exception translates to fail.")]
public static bool TryReadAsType(this JsonValue jsonValue, Type type, out object value)
{
if (jsonValue == null)
{
throw new ArgumentNullException("jsonValue");
}
if (type == null)
{
throw new ArgumentNullException("type");
}
if (type == typeof(JsonValue) || type == typeof(object))
{
value = jsonValue;
return true;
}
if (type == typeof(object[]) || type == typeof(Dictionary<string, object>))
{
if (!JsonValueExtensions.CanConvertToClrCollection(jsonValue, type))
{
value = null;
return false;
}
}
if (jsonValue.TryReadAs(type, out value))
{
return true;
}
try
{
using (MemoryStream ms = new MemoryStream())
{
jsonValue.Save(ms);
ms.Position = 0;
DataContractJsonSerializer dcjs = new DataContractJsonSerializer(type);
value = dcjs.ReadObject(ms);
}
return true;
}
catch (Exception)
{
value = null;
return false;
}
}
/// <summary>
/// Determines whether the specified <see cref="JsonValue"/> instance can be converted to the specified collection <see cref="Type"/>.
/// </summary>
/// <param name="jsonValue">The instance to be converted.</param>
/// <param name="collectionType">The collection type to convert the instance to.</param>
/// <returns>true if the instance can be converted, false otherwise</returns>
private static bool CanConvertToClrCollection(JsonValue jsonValue, Type collectionType)
{
if (jsonValue != null)
{
return (jsonValue.JsonType == JsonType.Object && collectionType == typeof(Dictionary<string, object>)) ||
(jsonValue.JsonType == JsonType.Array && collectionType == typeof(object[]));
}
return false;
}
private static JsonValue CreatePrimitive(object value)
{
JsonPrimitive jsonPrimitive;
if (JsonPrimitive.TryCreate(value, out jsonPrimitive))
{
return jsonPrimitive;
}
return null;
}
private static JsonValue CreateFromComplex(object value)
{
DataContractJsonSerializer dcjs = new DataContractJsonSerializer(value.GetType());
using (MemoryStream ms = new MemoryStream())
{
dcjs.WriteObject(ms, value);
ms.Position = 0;
return JsonValue.Load(ms);
}
}
[SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily", Justification = "value is not the same")]
private static JsonValue CreateFromDynamic(object value)
{
JsonObject parent = null;
DynamicObject dynObj = value as DynamicObject;
if (dynObj != null)
{
parent = new JsonObject();
Stack<CreateFromTypeStackInfo> infoStack = new Stack<CreateFromTypeStackInfo>();
IEnumerator<string> keys = null;
do
{
if (keys == null)
{
keys = dynObj.GetDynamicMemberNames().GetEnumerator();
}
while (keys.MoveNext())
{
JsonValue child = null;
string key = keys.Current;
SimpleGetMemberBinder binder = new SimpleGetMemberBinder(key);
if (dynObj.TryGetMember(binder, out value))
{
DynamicObject childDynObj = value as DynamicObject;
if (childDynObj != null)
{
child = new JsonObject();
parent.Add(key, child);
infoStack.Push(new CreateFromTypeStackInfo(parent, dynObj, keys));
parent = child as JsonObject;
dynObj = childDynObj;
keys = null;
break;
}
else
{
if (value != null)
{
child = value as JsonValue;
if (child == null)
{
child = JsonValueExtensions.CreatePrimitive(value);
if (child == null)
{
child = JsonValueExtensions.CreateFromComplex(value);
}
}
}
parent.Add(key, child);
}
}
}
if (infoStack.Count > 0 && keys != null)
{
CreateFromTypeStackInfo info = infoStack.Pop();
parent = info.JsonObject;
dynObj = info.DynamicObject;
keys = info.Keys;
}
}
while (infoStack.Count > 0);
}
return parent;
}
private class CreateFromTypeStackInfo
{
public CreateFromTypeStackInfo(JsonObject jsonObject, DynamicObject dynamicObject, IEnumerator<string> keyEnumerator)
{
JsonObject = jsonObject;
DynamicObject = dynamicObject;
Keys = keyEnumerator;
}
/// <summary>
/// Gets of sets
/// </summary>
public JsonObject JsonObject { get; set; }
/// <summary>
/// Gets of sets
/// </summary>
public DynamicObject DynamicObject { get; set; }
/// <summary>
/// Gets of sets
/// </summary>
public IEnumerator<string> Keys { get; set; }
}
private class SimpleGetMemberBinder : GetMemberBinder
{
public SimpleGetMemberBinder(string name)
: base(name, false)
{
}
public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject errorSuggestion)
{
if (target != null && errorSuggestion == null)
{
string exceptionMessage = RS.Format(System.Json.Properties.Resources.DynamicPropertyNotDefined, target.LimitType, Name);
Expression throwExpression = Expression.Throw(Expression.Constant(new InvalidOperationException(exceptionMessage)), typeof(object));
errorSuggestion = new DynamicMetaObject(throwExpression, target.Restrictions);
}
return errorSuggestion;
}
}
}
}
#endif

View File

@@ -0,0 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Diagnostics.CodeAnalysis;
[assembly: SuppressMessage("Microsoft.Design", "CA2210:AssembliesShouldHaveValidStrongNames", Justification = "These assemblies are delay-signed.")]
[assembly: SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Justification = "Classes are grouped logically for user clarity.", Scope = "namespace", Target = "System.Runtime.Serialization.Json")]

View File

@@ -0,0 +1,304 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Runtime.Serialization.Json;
using System.Text;
using System.Xml;
namespace System.Json
{
internal static class JXmlToJsonValueConverter
{
internal const string RootElementName = "root";
internal const string ItemElementName = "item";
internal const string TypeAttributeName = "type";
internal const string ArrayAttributeValue = "array";
internal const string BooleanAttributeValue = "boolean";
internal const string NullAttributeValue = "null";
internal const string NumberAttributeValue = "number";
internal const string ObjectAttributeValue = "object";
internal const string StringAttributeValue = "string";
private const string TypeHintAttributeName = "__type";
private static readonly char[] _floatingPointChars = new char[] { '.', 'e', 'E' };
public static JsonValue JXMLToJsonValue(Stream jsonStream)
{
if (jsonStream == null)
{
throw new ArgumentNullException("jsonStream");
}
return JXMLToJsonValue(jsonStream, null);
}
public static JsonValue JXMLToJsonValue(string jsonString)
{
if (jsonString == null)
{
throw new ArgumentNullException("jsonString");
}
if (jsonString.Length == 0)
{
throw new ArgumentException(Properties.Resources.JsonStringCannotBeEmpty, "jsonString");
}
byte[] jsonBytes = Encoding.UTF8.GetBytes(jsonString);
return JXMLToJsonValue(null, jsonBytes);
}
public static JsonValue JXMLToJsonValue(XmlDictionaryReader jsonReader)
{
if (jsonReader == null)
{
throw new ArgumentNullException("jsonReader");
}
const string RootObjectName = "RootObject";
Stack<JsonValue> jsonStack = new Stack<JsonValue>();
string nodeType = null;
bool isEmptyElement = false;
JsonValue parent = new JsonObject();
jsonStack.Push(parent);
string currentName = RootObjectName;
try
{
MoveToRootNode(jsonReader);
while (jsonStack.Count > 0 && jsonReader.NodeType != XmlNodeType.None)
{
if (parent is JsonObject && currentName == null)
{
currentName = GetMemberName(jsonReader);
}
nodeType = jsonReader.GetAttribute(TypeAttributeName) ?? StringAttributeValue;
if (parent is JsonArray)
{
// For arrays, the element name has to be "item"
if (jsonReader.Name != ItemElementName)
{
throw new FormatException(Properties.Resources.IncorrectJsonFormat);
}
}
switch (nodeType)
{
case NullAttributeValue:
case BooleanAttributeValue:
case StringAttributeValue:
case NumberAttributeValue:
JsonPrimitive jsonPrimitive = ReadPrimitive(nodeType, jsonReader);
InsertJsonValue(jsonStack, ref parent, ref currentName, jsonPrimitive, true);
break;
case ArrayAttributeValue:
JsonArray jsonArray = CreateJsonArray(jsonReader, ref isEmptyElement);
InsertJsonValue(jsonStack, ref parent, ref currentName, jsonArray, isEmptyElement);
break;
case ObjectAttributeValue:
JsonObject jsonObject = CreateObjectWithTypeHint(jsonReader, ref isEmptyElement);
InsertJsonValue(jsonStack, ref parent, ref currentName, jsonObject, isEmptyElement);
break;
default:
throw new FormatException(Properties.Resources.IncorrectJsonFormat);
}
while (jsonReader.NodeType == XmlNodeType.EndElement && jsonStack.Count > 0)
{
jsonReader.Read();
SkipWhitespace(jsonReader);
jsonStack.Pop();
if (jsonStack.Count > 0)
{
parent = jsonStack.Peek();
}
}
}
}
catch (XmlException xmlException)
{
throw new FormatException(Properties.Resources.IncorrectJsonFormat, xmlException);
}
if (jsonStack.Count != 1)
{
throw new FormatException(Properties.Resources.IncorrectJsonFormat);
}
return parent[RootObjectName];
}
private static JsonValue JXMLToJsonValue(Stream jsonStream, byte[] jsonBytes)
{
try
{
using (XmlDictionaryReader jsonReader =
jsonStream != null
? JsonReaderWriterFactory.CreateJsonReader(jsonStream, XmlDictionaryReaderQuotas.Max)
: JsonReaderWriterFactory.CreateJsonReader(jsonBytes, XmlDictionaryReaderQuotas.Max))
{
return JXMLToJsonValue(jsonReader);
}
}
catch (XmlException)
{
throw new FormatException(Properties.Resources.IncorrectJsonFormat);
}
}
private static void InsertJsonValue(Stack<JsonValue> jsonStack, ref JsonValue parent, ref string currentName, JsonValue jsonValue, bool isEmptyElement)
{
if (parent is JsonArray)
{
((JsonArray)parent).Add(jsonValue);
}
else
{
if (currentName != null)
{
((JsonObject)parent)[currentName] = jsonValue;
currentName = null;
}
}
if (!isEmptyElement)
{
jsonStack.Push(jsonValue);
parent = jsonValue;
}
}
private static string GetMemberName(XmlDictionaryReader jsonReader)
{
string name;
if (jsonReader.NamespaceURI == ItemElementName && jsonReader.LocalName == ItemElementName)
{
// JXML special case for names which aren't valid XML names
name = jsonReader.GetAttribute(ItemElementName);
if (name == null)
{
throw new FormatException(Properties.Resources.IncorrectJsonFormat);
}
}
else
{
name = jsonReader.Name;
}
return name;
}
private static JsonObject CreateObjectWithTypeHint(XmlDictionaryReader jsonReader, ref bool isEmptyElement)
{
JsonObject jsonObject = new JsonObject();
string typeHintAttribute = jsonReader.GetAttribute(TypeHintAttributeName);
isEmptyElement = jsonReader.IsEmptyElement;
jsonReader.ReadStartElement();
SkipWhitespace(jsonReader);
if (typeHintAttribute != null)
{
jsonObject.Add(TypeHintAttributeName, typeHintAttribute);
}
return jsonObject;
}
private static JsonArray CreateJsonArray(XmlDictionaryReader jsonReader, ref bool isEmptyElement)
{
JsonArray jsonArray = new JsonArray();
isEmptyElement = jsonReader.IsEmptyElement;
jsonReader.ReadStartElement();
SkipWhitespace(jsonReader);
return jsonArray;
}
private static void MoveToRootNode(XmlDictionaryReader jsonReader)
{
while (!jsonReader.EOF && (jsonReader.NodeType == XmlNodeType.None || jsonReader.NodeType == XmlNodeType.XmlDeclaration))
{
// read into <root> node
jsonReader.Read();
SkipWhitespace(jsonReader);
}
if (jsonReader.NodeType != XmlNodeType.Element || !String.IsNullOrEmpty(jsonReader.NamespaceURI) || jsonReader.Name != RootElementName)
{
throw new FormatException(Properties.Resources.IncorrectJsonFormat);
}
}
private static JsonPrimitive ReadPrimitive(string type, XmlDictionaryReader jsonReader)
{
JsonValue result = null;
switch (type)
{
case NullAttributeValue:
jsonReader.Skip();
result = null;
break;
case BooleanAttributeValue:
result = jsonReader.ReadElementContentAsBoolean();
break;
case StringAttributeValue:
result = jsonReader.ReadElementContentAsString();
break;
case NumberAttributeValue:
string temp = jsonReader.ReadElementContentAsString();
result = ConvertStringToJsonNumber(temp);
break;
}
SkipWhitespace(jsonReader);
return (JsonPrimitive)result;
}
private static void SkipWhitespace(XmlDictionaryReader reader)
{
while (!reader.EOF && (reader.NodeType == XmlNodeType.Whitespace || reader.NodeType == XmlNodeType.SignificantWhitespace))
{
reader.Read();
}
}
private static JsonValue ConvertStringToJsonNumber(string value)
{
if (value.IndexOfAny(_floatingPointChars) < 0)
{
int intVal;
if (Int32.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out intVal))
{
return intVal;
}
long longVal;
if (Int64.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out longVal))
{
return longVal;
}
}
decimal decValue;
if (Decimal.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out decValue) && decValue != 0)
{
return decValue;
}
double dblValue;
if (Double.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out dblValue))
{
return dblValue;
}
throw new ArgumentException(RS.Format(Properties.Resources.InvalidJsonPrimitive, value.ToString()), "value");
}
}
}

View File

@@ -0,0 +1,389 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Runtime.Serialization;
using System.Xml;
namespace System.Json
{
/// <summary>
/// A JsonArray is an ordered sequence of zero or more <see cref="System.Json.JsonValue"/> objects.
/// </summary>
[SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix",
Justification = "Array already conveys the meaning of collection")]
[DataContract]
public sealed class JsonArray : JsonValue, IList<JsonValue>
{
[DataMember]
private List<JsonValue> values = new List<JsonValue>();
/// <summary>
/// Creates an instance of the <see cref="System.Json.JsonArray"/> class initialized by
/// an <see cref="System.Collections.Generic.IEnumerable{T}"/> enumeration of
/// objects of type <see cref="System.Json.JsonValue"/>.
/// </summary>
/// <param name="items">The <see cref="System.Collections.Generic.IEnumerable{T}"/> enumeration
/// of objects of type <see cref="System.Json.JsonValue"/> used to initialize the JavaScript Object Notation (JSON)
/// array.</param>
/// <exception cref="System.ArgumentNullException">If items is null.</exception>
/// <exception cref="System.ArgumentException">If any of the items in the collection
/// is a <see cref="System.Json.JsonValue"/> with <see cref="System.Json.JsonValue.JsonType"/> property of
/// value <see cref="F:System.Json.JsonType.Default"/>.</exception>
public JsonArray(IEnumerable<JsonValue> items)
{
AddRange(items);
}
/// <summary>
/// Creates an instance of the <see cref="System.Json.JsonArray"/> class, initialized by an array of type <see cref="System.Json.JsonValue"/>.
/// </summary>
/// <param name="items">The array of type <see cref="System.Json.JsonValue"/> used to initialize the
/// JavaScript Object Notation (JSON) array.</param>
/// <exception cref="System.ArgumentException">If any of the items in the collection
/// is a <see cref="System.Json.JsonValue"/> with <see cref="System.Json.JsonValue.JsonType"/> property of
/// value <see cref="F:System.Json.JsonType.Default"/>.</exception>
public JsonArray(params JsonValue[] items)
{
if (items != null)
{
AddRange(items);
}
}
/// <summary>
/// Gets the JSON type of this <see cref="System.Json.JsonArray"/>. The return value
/// is always <see cref="F:System.Json.JsonType.Array"/>.
/// </summary>
public override JsonType JsonType
{
get { return JsonType.Array; }
}
/// <summary>
/// Gets a value indicating whether the <see cref="System.Json.JsonArray"/> is read-only.
/// </summary>
public bool IsReadOnly
{
get { return ((IList)values).IsReadOnly; }
}
/// <summary>
/// Returns the number of <see cref="System.Json.JsonValue"/> elements in the array.
/// </summary>
public override int Count
{
get { return values.Count; }
}
/// <summary>
/// Gets or sets the JSON value at a specified index.
/// </summary>
/// <param name="index">The zero-based index of the element to get or set.</param>
/// <returns>The <see cref="System.Json.JsonValue"/> element at the specified index.</returns>
/// <exception cref="System.ArgumentOutOfRangeException">If index is not a valid index for this array.</exception>
/// <exception cref="System.ArgumentException">The property is set and the value is a
/// <see cref="System.Json.JsonValue"/> with <see cref="System.Json.JsonValue.JsonType"/>
/// property of value <see cref="F:System.Json.JsonType.Default"/>.</exception>
public override JsonValue this[int index]
{
get { return values[index]; }
set
{
if (value != null && value.JsonType == JsonType.Default)
{
throw new ArgumentNullException("value", Properties.Resources.UseOfDefaultNotAllowed);
}
JsonValue oldValue = values[index];
RaiseItemChanging(value, JsonValueChange.Replace, index);
values[index] = value;
RaiseItemChanged(oldValue, JsonValueChange.Replace, index);
}
}
/// <summary>
/// Adds the elements from a collection of type <see cref="System.Json.JsonValue"/> to this instance.
/// </summary>
/// <param name="items">Collection of items to add.</param>
/// <exception cref="System.ArgumentNullException">If items is null.</exception>
/// <exception cref="System.ArgumentException">If any of the items in the collection
/// is a <see cref="System.Json.JsonValue"/> with <see cref="System.Json.JsonValue.JsonType"/> property of
/// value <see cref="F:System.Json.JsonType.Default"/>.</exception>
public void AddRange(IEnumerable<JsonValue> items)
{
if (items == null)
{
throw new ArgumentNullException("items");
}
if (ChangingListenersCount > 0)
{
int index = Count;
foreach (JsonValue toBeAdded in items)
{
RaiseItemChanging(toBeAdded, JsonValueChange.Add, index++);
}
}
foreach (JsonValue item in items)
{
if (item != null && item.JsonType == JsonType.Default)
{
throw new ArgumentNullException("items", Properties.Resources.UseOfDefaultNotAllowed);
}
values.Add(item);
RaiseItemChanged(item, JsonValueChange.Add, values.Count - 1);
}
}
/// <summary>
/// Adds the elements from an array of type <see cref="System.Json.JsonValue"/> to this instance.
/// </summary>
/// <param name="items">The array of type JsonValue to be added to this instance.</param>
/// <exception cref="System.ArgumentNullException">If items is null.</exception>
/// <exception cref="System.ArgumentException">If any of the items in the array
/// is a <see cref="System.Json.JsonValue"/> with <see cref="System.Json.JsonValue.JsonType"/> property of
/// value <see cref="F:System.Json.JsonType.Default"/>.</exception>
public void AddRange(params JsonValue[] items)
{
AddRange(items as IEnumerable<JsonValue>);
}
/// <summary>
/// Searches for a specified object and returns the zero-based index of its first
/// occurrence within this <see cref="System.Json.JsonArray"/>.
/// </summary>
/// <param name="item">The <see cref="System.Json.JsonValue"/> object to look up.</param>
/// <returns>The zero-based index of the first occurrence of item within the
/// <see cref="System.Json.JsonArray"/>, if found; otherwise, -1.</returns>
public int IndexOf(JsonValue item)
{
return values.IndexOf(item);
}
/// <summary>
/// Insert a JSON CLR type into the array at a specified index.
/// </summary>
/// <param name="index">The zero-based index at which the item should be inserted.</param>
/// <param name="item">The <see cref="System.Json.JsonValue"/> object to insert.</param>
/// <exception cref="System.ArgumentOutOfRangeException">If index is less than zero or larger than
/// the size of the array.</exception>
/// <exception cref="System.ArgumentException">If the object to insert has a
/// <see cref="System.Json.JsonValue.JsonType"/> property of value
/// <see cref="F:System.Json.JsonType.Default"/>.</exception>
public void Insert(int index, JsonValue item)
{
if (item != null && item.JsonType == JsonType.Default)
{
throw new ArgumentNullException("item", Properties.Resources.UseOfDefaultNotAllowed);
}
RaiseItemChanging(item, JsonValueChange.Add, index);
values.Insert(index, item);
RaiseItemChanged(item, JsonValueChange.Add, index);
}
/// <summary>
/// Remove the JSON value at a specified index of <see cref="System.Json.JsonArray"/>.
/// </summary>
/// <param name="index">The zero-based index at which to remove the <see cref="System.Json.JsonValue"/>.</param>
/// <exception cref="System.ArgumentOutOfRangeException">If index is less than zero or index
/// is equal or larger than the size of the array.</exception>
public void RemoveAt(int index)
{
JsonValue item = values[index];
RaiseItemChanging(item, JsonValueChange.Remove, index);
values.RemoveAt(index);
RaiseItemChanged(item, JsonValueChange.Remove, index);
}
/// <summary>
/// Adds a <see cref="System.Json.JsonValue"/> object to the end of the array.
/// </summary>
/// <param name="item">The <see cref="System.Json.JsonValue"/> object to add.</param>
/// <exception cref="System.ArgumentException">If the object to add has a
/// <see cref="System.Json.JsonValue.JsonType"/> property of value
/// <see cref="F:System.Json.JsonType.Default"/>.</exception>
public void Add(JsonValue item)
{
if (item != null && item.JsonType == JsonType.Default)
{
throw new ArgumentNullException("item", Properties.Resources.UseOfDefaultNotAllowed);
}
int index = Count;
RaiseItemChanging(item, JsonValueChange.Add, index);
values.Add(item);
RaiseItemChanged(item, JsonValueChange.Add, index);
}
/// <summary>
/// Removes all JSON CLR types from the <see cref="System.Json.JsonArray"/>.
/// </summary>
public void Clear()
{
RaiseItemChanging(null, JsonValueChange.Clear, 0);
values.Clear();
RaiseItemChanged(null, JsonValueChange.Clear, 0);
}
/// <summary>
/// Checks whether a specified JSON CLR type is in the <see cref="System.Json.JsonArray"/>.
/// </summary>
/// <param name="item">The <see cref="System.Json.JsonValue"/> to check for in the array.</param>
/// <returns>true if item is found in the <see cref="System.Json.JsonArray"/>; otherwise, false.</returns>
public bool Contains(JsonValue item)
{
return values.Contains(item);
}
/// <summary>
/// Copies the contents of the current JSON CLR array instance into a specified
/// destination array beginning at the specified index.
/// </summary>
/// <param name="array">The destination array to which the elements of the current
/// <see cref="System.Json.JsonArray"/> object are copied.</param>
/// <param name="arrayIndex">The zero-based index in the destination array at which the
/// copying of the elements of the JSON CLR array begins.</param>
public void CopyTo(JsonValue[] array, int arrayIndex)
{
values.CopyTo(array, arrayIndex);
}
/// <summary>
/// Removes the first occurrence of the specified JSON value from the array.
/// </summary>
/// <param name="item">The <see cref="System.Json.JsonValue"/> to remove from the <see cref="System.Json.JsonArray"/>.</param>
/// <returns>true if item is successfully removed; otherwise, false. This method
/// also returns false if item was not found in the <see cref="System.Json.JsonArray"/>.</returns>
public bool Remove(JsonValue item)
{
int index = -1;
if (ChangingListenersCount > 0 || ChangedListenersCount > 0)
{
index = IndexOf(item);
}
if (index >= 0)
{
RaiseItemChanging(item, JsonValueChange.Remove, index);
}
bool result = values.Remove(item);
if (index >= 0)
{
RaiseItemChanged(item, JsonValueChange.Remove, index);
}
return result;
}
/// <summary>
/// Returns an enumerator that iterates through the <see cref="System.Json.JsonValue"/> objects in the array.
/// </summary>
/// <returns>Returns an <see cref="System.Collections.IEnumerator"/> object that
/// iterates through the <see cref="System.Json.JsonValue"/> elements in this <see cref="System.Json.JsonArray"/>.</returns>
IEnumerator IEnumerable.GetEnumerator()
{
return values.GetEnumerator();
}
/// <summary>
/// Safe indexer for the <see cref="System.Json.JsonValue"/> type.
/// </summary>
/// <param name="index">The zero-based index of the element to get.</param>
/// <returns>If the index is within the array bounds and the value corresponding to the
/// index is not null, then it will return that value. Otherwise it will return a
/// <see cref="System.Json.JsonValue"/> instance with <see cref="System.Json.JsonValue.JsonType"/>
/// equals to <see cref="F:System.Json.JsonType.Default"/>.</returns>
public override JsonValue ValueOrDefault(int index)
{
if (index >= 0 && index < Count && this[index] != null)
{
return this[index];
}
return base.ValueOrDefault(index);
}
/// <summary>
/// Returns an enumerator that iterates through the <see cref="System.Json.JsonValue"/> objects in the array.
/// </summary>
/// <returns>Returns an <see cref="System.Collections.Generic.IEnumerator{T}"/> object that
/// iterates through the <see cref="System.Json.JsonValue"/> elements in this <see cref="System.Json.JsonArray"/>.</returns>
public new IEnumerator<JsonValue> GetEnumerator()
{
return values.GetEnumerator();
}
/// <summary>
/// Returns an enumerator which iterates through the values in this object.
/// </summary>
/// <returns>An <see cref="System.Collections.Generic.IEnumerator{T}"/> which iterates through the values in this object.</returns>
/// <remarks>The enumerator returned by this class contains one pair for each element
/// in this array, whose key is the element index (as a string), and the value is the
/// element itself.</remarks>
protected override IEnumerator<KeyValuePair<string, JsonValue>> GetKeyValuePairEnumerator()
{
for (int i = 0; i < values.Count; i++)
{
yield return new KeyValuePair<string, JsonValue>(i.ToString(CultureInfo.InvariantCulture), values[i]);
}
}
/// <summary>
/// Callback method called to let an instance write the proper JXML attribute when saving this
/// instance.
/// </summary>
/// <param name="jsonWriter">The JXML writer used to write JSON.</param>
internal override void WriteAttributeString(XmlDictionaryWriter jsonWriter)
{
if (jsonWriter == null)
{
throw new ArgumentNullException("jsonWriter");
}
jsonWriter.WriteAttributeString(JXmlToJsonValueConverter.TypeAttributeName, JXmlToJsonValueConverter.ArrayAttributeValue);
}
/// <summary>
/// Callback method called during Save operations to let the instance write the start element
/// and return the next element in the collection.
/// </summary>
/// <param name="jsonWriter">The JXML writer used to write JSON.</param>
/// <param name="currentIndex">The index within this collection.</param>
/// <returns>The next item in the collection, or null of there are no more items.</returns>
internal override JsonValue WriteStartElementAndGetNext(XmlDictionaryWriter jsonWriter, int currentIndex)
{
if (jsonWriter == null)
{
throw new ArgumentNullException("jsonWriter");
}
jsonWriter.WriteStartElement(JXmlToJsonValueConverter.ItemElementName);
JsonValue nextValue = this[currentIndex];
return nextValue;
}
private void RaiseItemChanging(JsonValue child, JsonValueChange change, int index)
{
if (ChangingListenersCount > 0)
{
RaiseChangingEvent(this, new JsonValueChangeEventArgs(child, change, index));
}
}
private void RaiseItemChanged(JsonValue child, JsonValueChange change, int index)
{
if (ChangedListenersCount > 0)
{
RaiseChangedEvent(this, new JsonValueChangeEventArgs(child, change, index));
}
}
}
}

View File

@@ -0,0 +1,474 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.Serialization;
using System.Xml;
using WrappedPair = System.Json.NGenWrapper<System.Collections.Generic.KeyValuePair<string, System.Json.JsonValue>>;
namespace System.Json
{
/// <summary>
/// A JsonObject is an unordered collection of zero or more key/value pairs.
/// </summary>
/// <remarks>A JsonObject is an unordered collection of zero or more key/value pairs,
/// where each key is a String and each value is a <see cref="System.Json.JsonValue"/>, which can be a
/// <see cref="System.Json.JsonPrimitive"/>, a <see cref="System.Json.JsonArray"/>, or a JsonObject.</remarks>
[SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix",
Justification = "Object in the context of JSON already conveys the meaning of dictionary")]
[DataContract]
public sealed class JsonObject : JsonValue, IDictionary<string, JsonValue>
{
[DataMember]
private Dictionary<string, JsonValue> values = new Dictionary<string, JsonValue>(StringComparer.Ordinal);
private List<WrappedPair> indexedPairs;
private int instanceSaveCount;
private object saveLock = new object();
/// <summary>
/// Creates an instance of the <see cref="System.Json.JsonObject"/> class initialized with an
/// <see cref="System.Collections.Generic.IEnumerable{T}"/> collection of key/value pairs.
/// </summary>
/// <param name="items">The <see cref="System.Collections.Generic.IEnumerable{T}"/> collection of
/// <see cref="System.Collections.Generic.KeyValuePair{K, V}"/> used to initialize the
/// key/value pairs</param>
/// <exception cref="System.ArgumentNullException">If items is null.</exception>
/// <exception cref="System.ArgumentException">If any of the values in the collection
/// is a <see cref="System.Json.JsonValue"/> with <see cref="System.Json.JsonValue.JsonType"/> property of
/// value <see cref="F:System.Json.JsonType.Default"/>.</exception>
[SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures",
Justification = "There's no complexity using this design because nested generic type is atomic type not another collection")]
public JsonObject(IEnumerable<KeyValuePair<string, JsonValue>> items)
{
AddRange(items);
}
/// <summary>
/// Creates an instance of the <see cref="System.Json.JsonObject"/> class initialized with a collection of key/value pairs.
/// </summary>
/// <param name="items">The <see cref="System.Collections.Generic.KeyValuePair{K, V}"/> objects used to initialize the key/value pairs.</param>
/// <exception cref="System.ArgumentException">If any of the values in the collection
/// is a <see cref="System.Json.JsonValue"/> with <see cref="System.Json.JsonValue.JsonType"/> property of
/// value <see cref="F:System.Json.JsonType.Default"/>.</exception>
public JsonObject(params KeyValuePair<string, JsonValue>[] items)
{
if (items != null)
{
AddRange(items);
}
}
/// <summary>
/// Gets the JSON type of this <see cref="System.Json.JsonObject"/>. The return value
/// is always <see cref="F:System.Json.JsonType.Object"/>.
/// </summary>
public override JsonType JsonType
{
get { return JsonType.Object; }
}
/// <summary>
/// Gets a collection that contains the keys in this <see cref="System.Json.JsonObject"/>.
/// </summary>
public ICollection<string> Keys
{
get { return values.Keys; }
}
/// <summary>
/// Gets a collection that contains the values in this <see cref="System.Json.JsonObject"/>.
/// </summary>
public ICollection<JsonValue> Values
{
get { return values.Values; }
}
/// <summary>
/// Returns the number of key/value pairs in this <see cref="System.Json.JsonObject"/>.
/// </summary>
public override int Count
{
get { return values.Count; }
}
/// <summary>
/// Gets a value indicating whether this JSON CLR object is read-only.
/// </summary>
bool ICollection<KeyValuePair<string, JsonValue>>.IsReadOnly
{
get { return ((ICollection<KeyValuePair<string, JsonValue>>)values).IsReadOnly; }
}
/// <summary>
/// Gets or sets the value associated with the specified key.
/// </summary>
/// <param name="key">The key of the value to get or set.</param>
/// <returns>The <see cref="System.Json.JsonValue"/> associated to the specified key.</returns>
/// <exception cref="System.ArgumentNullException">If key is null.</exception>
/// <exception cref="System.ArgumentException">The property is set and the value is a
/// <see cref="System.Json.JsonValue"/> with <see cref="System.Json.JsonValue.JsonType"/>
/// property of value <see cref="F:System.Json.JsonType.Default"/>.</exception>
public override JsonValue this[string key]
{
get
{
if (key == null)
{
throw new ArgumentNullException("key");
}
return values[key];
}
set
{
if (value != null && value.JsonType == JsonType.Default)
{
throw new ArgumentNullException("value", Properties.Resources.UseOfDefaultNotAllowed);
}
if (key == null)
{
throw new ArgumentNullException("key");
}
bool replacement = values.ContainsKey(key);
JsonValue oldValue = null;
if (replacement)
{
oldValue = values[key];
RaiseItemChanging(value, JsonValueChange.Replace, key);
}
else
{
RaiseItemChanging(value, JsonValueChange.Add, key);
}
values[key] = value;
if (replacement)
{
RaiseItemChanged(oldValue, JsonValueChange.Replace, key);
}
else
{
RaiseItemChanged(value, JsonValueChange.Add, key);
}
}
}
/// <summary>
/// Safe string indexer for the <see cref="System.Json.JsonValue"/> type.
/// </summary>
/// <param name="key">The key of the element to get.</param>
/// <returns>If this instance contains the given key and the value corresponding to
/// the key is not null, then it will return that value. Otherwise it will return a
/// <see cref="System.Json.JsonValue"/> instance with <see cref="System.Json.JsonValue.JsonType"/>
/// equals to <see cref="F:System.Json.JsonType.Default"/>.</returns>
public override JsonValue ValueOrDefault(string key)
{
if (key != null && ContainsKey(key) && this[key] != null)
{
return this[key];
}
return base.ValueOrDefault(key);
}
/// <summary>
/// Adds a specified collection of key/value pairs to this instance.
/// </summary>
/// <param name="items">The collection of key/value pairs to add.</param>
/// <exception cref="System.ArgumentNullException">If items is null.</exception>
/// <exception cref="System.ArgumentException">If the value of any of the items in the collection
/// is a <see cref="System.Json.JsonValue"/> with <see cref="System.Json.JsonValue.JsonType"/> property of
/// value <see cref="F:System.Json.JsonType.Default"/>.</exception>
[SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures",
Justification = "There's no complexity using this design because nested generic type is atomic type not another collection")]
public void AddRange(IEnumerable<KeyValuePair<string, JsonValue>> items)
{
if (items == null)
{
throw new ArgumentNullException("items");
}
if (ChangingListenersCount > 0)
{
foreach (KeyValuePair<string, JsonValue> item in items)
{
RaiseItemChanging(item.Value, JsonValueChange.Add, item.Key);
}
}
foreach (KeyValuePair<string, JsonValue> item in items)
{
if (item.Value != null && item.Value.JsonType == JsonType.Default)
{
throw new ArgumentNullException("items", Properties.Resources.UseOfDefaultNotAllowed);
}
values.Add(item.Key, item.Value);
RaiseItemChanged(item.Value, JsonValueChange.Add, item.Key);
}
}
/// <summary>
/// Adds the elements from an array of type <see cref="System.Json.JsonValue"/> to this instance.
/// </summary>
/// <param name="items">The array of key/value paris to be added to this instance.</param>
/// <exception cref="System.ArgumentException">If the value of any of the items in the array
/// is a <see cref="System.Json.JsonValue"/> with <see cref="System.Json.JsonValue.JsonType"/> property of
/// value <see cref="F:System.Json.JsonType.Default"/>.</exception>
public void AddRange(params KeyValuePair<string, JsonValue>[] items)
{
AddRange(items as IEnumerable<KeyValuePair<string, JsonValue>>);
}
/// <summary>
///
/// </summary>
/// <returns></returns>
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable)values).GetEnumerator();
}
/// <summary>
/// Adds a key/value pair to this <see cref="System.Json.JsonObject"/> instance.
/// </summary>
/// <param name="key">The key for the element added.</param>
/// <param name="value">The <see cref="System.Json.JsonValue"/> for the element added.</param>
/// <exception cref="System.ArgumentException">If the value is a <see cref="System.Json.JsonValue"/>
/// with <see cref="System.Json.JsonValue.JsonType"/> property of
/// value <see cref="F:System.Json.JsonType.Default"/>.</exception>
public void Add(string key, JsonValue value)
{
if (value != null && value.JsonType == JsonType.Default)
{
throw new ArgumentNullException("value", Properties.Resources.UseOfDefaultNotAllowed);
}
RaiseItemChanging(value, JsonValueChange.Add, key);
values.Add(key, value);
RaiseItemChanged(value, JsonValueChange.Add, key);
}
/// <summary>
/// Adds a key/value pair to this <see cref="System.Json.JsonObject"/> instance.
/// </summary>
/// <param name="item">The key/value pair to be added.</param>
/// <exception cref="System.ArgumentException">If the value of the pair is a
/// <see cref="System.Json.JsonValue"/> with <see cref="System.Json.JsonValue.JsonType"/>
/// property of value <see cref="F:System.Json.JsonType.Default"/>.</exception>
public void Add(KeyValuePair<string, JsonValue> item)
{
Add(item.Key, item.Value);
}
/// <summary>
/// Checks whether a key/value pair with a specified key exists in this <see cref="System.Json.JsonObject"/> instance.
/// </summary>
/// <param name="key">The key to check for.</param>
/// <returns>true if this instance contains the key; otherwise, false.</returns>
public override bool ContainsKey(string key)
{
return values.ContainsKey(key);
}
/// <summary>
/// Removes the key/value pair with a specified key from this <see cref="System.Json.JsonObject"/> instance.
/// </summary>
/// <param name="key">The key of the item to remove.</param>
/// <returns>true if the element is successfully found and removed; otherwise, false.
/// This method returns false if key is not found in this <see cref="System.Json.JsonObject"/> instance.</returns>
public bool Remove(string key)
{
JsonValue original = null;
bool containsKey = false;
if (ChangingListenersCount > 0 || ChangedListenersCount > 0)
{
containsKey = TryGetValue(key, out original);
}
if (containsKey && ChangingListenersCount > 0)
{
RaiseItemChanging(original, JsonValueChange.Remove, key);
}
bool result = values.Remove(key);
if (containsKey && ChangedListenersCount > 0)
{
RaiseItemChanged(original, JsonValueChange.Remove, key);
}
return result;
}
/// <summary>
/// Attempts to get the value that corresponds to the specified key.
/// </summary>
/// <param name="key">The key of the value to retrieve.</param>
/// <param name="value">The primitive or structured <see cref="System.Json.JsonValue"/> object that has the key
/// specified. If this object does not contain a key/value pair with the given key,
/// this parameter is set to null.</param>
/// <returns>true if the instance of the <see cref="System.Json.JsonObject"/> contains an element with the
/// specified key; otherwise, false.</returns>
public bool TryGetValue(string key, out JsonValue value)
{
return values.TryGetValue(key, out value);
}
/// <summary>
/// Removes all key/value pairs from this <see cref="System.Json.JsonObject"/> instance.
/// </summary>
public void Clear()
{
RaiseItemChanging(null, JsonValueChange.Clear, null);
values.Clear();
RaiseItemChanged(null, JsonValueChange.Clear, null);
}
bool ICollection<KeyValuePair<string, JsonValue>>.Contains(KeyValuePair<string, JsonValue> item)
{
return ((ICollection<KeyValuePair<string, JsonValue>>)values).Contains(item);
}
/// <summary>
/// Copies the contents of this <see cref="System.Json.JsonObject"/> instance into a specified
/// key/value destination array beginning at a specified index.
/// </summary>
/// <param name="array">The destination array of type <see cref="System.Collections.Generic.KeyValuePair{K, V}"/>
/// to which the elements of this <see cref="System.Json.JsonObject"/> are copied.</param>
/// <param name="arrayIndex">The zero-based index at which to begin the insertion of the
/// contents from this <see cref="System.Json.JsonObject"/> instance.</param>
public void CopyTo(KeyValuePair<string, JsonValue>[] array, int arrayIndex)
{
((ICollection<KeyValuePair<string, JsonValue>>)values).CopyTo(array, arrayIndex);
}
bool ICollection<KeyValuePair<string, JsonValue>>.Remove(KeyValuePair<string, JsonValue> item)
{
if (ChangingListenersCount > 0)
{
if (ContainsKey(item.Key) && EqualityComparer<JsonValue>.Default.Equals(item.Value, values[item.Key]))
{
RaiseItemChanging(item.Value, JsonValueChange.Remove, item.Key);
}
}
bool result = ((ICollection<KeyValuePair<string, JsonValue>>)values).Remove(item);
if (result)
{
RaiseItemChanged(item.Value, JsonValueChange.Remove, item.Key);
}
return result;
}
/// <summary>
/// Returns an enumerator over the key/value pairs contained in this <see cref="System.Json.JsonObject"/> instance.
/// </summary>
/// <returns>An <see cref="System.Collections.Generic.IEnumerator{T}"/> which iterates
/// through the members of this instance.</returns>
protected override IEnumerator<KeyValuePair<string, JsonValue>> GetKeyValuePairEnumerator()
{
return values.GetEnumerator();
}
/// <summary>
/// Callback method called when a Save operation is starting for this instance.
/// </summary>
protected override void OnSaveStarted()
{
lock (saveLock)
{
instanceSaveCount++;
if (indexedPairs == null)
{
indexedPairs = new List<WrappedPair>();
foreach (KeyValuePair<string, JsonValue> item in values)
{
indexedPairs.Add(new WrappedPair(item));
}
}
}
}
/// <summary>
/// Callback method called when a Save operation is finished for this instance.
/// </summary>
protected override void OnSaveEnded()
{
lock (saveLock)
{
instanceSaveCount--;
if (instanceSaveCount == 0)
{
indexedPairs = null;
}
}
}
/// <summary>
/// Callback method called to let an instance write the proper JXML attribute when saving this
/// instance.
/// </summary>
/// <param name="jsonWriter">The JXML writer used to write JSON.</param>
internal override void WriteAttributeString(XmlDictionaryWriter jsonWriter)
{
jsonWriter.WriteAttributeString(JXmlToJsonValueConverter.TypeAttributeName, JXmlToJsonValueConverter.ObjectAttributeValue);
}
/// <summary>
/// Callback method called during Save operations to let the instance write the start element
/// and return the next element in the collection.
/// </summary>
/// <param name="jsonWriter">The JXML writer used to write JSON.</param>
/// <param name="currentIndex">The index within this collection.</param>
/// <returns>The next item in the collection, or null of there are no more items.</returns>
internal override JsonValue WriteStartElementAndGetNext(XmlDictionaryWriter jsonWriter, int currentIndex)
{
KeyValuePair<string, JsonValue> currentPair = indexedPairs[currentIndex];
string currentKey = currentPair.Key;
if (currentKey.Length == 0)
{
// special case in JXML world
jsonWriter.WriteStartElement(JXmlToJsonValueConverter.ItemElementName, JXmlToJsonValueConverter.ItemElementName);
jsonWriter.WriteAttributeString(JXmlToJsonValueConverter.ItemElementName, String.Empty);
}
else
{
jsonWriter.WriteStartElement(currentKey);
}
return currentPair.Value;
}
[SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", Justification = "Context is required by CLR for this to work.")]
[OnDeserialized]
private void OnDeserialized(StreamingContext context)
{
saveLock = new object();
}
private void RaiseItemChanging(JsonValue child, JsonValueChange change, string key)
{
if (ChangingListenersCount > 0)
{
RaiseChangingEvent(this, new JsonValueChangeEventArgs(child, change, key));
}
}
private void RaiseItemChanged(JsonValue child, JsonValueChange change, string key)
{
if (ChangedListenersCount > 0)
{
RaiseChangedEvent(this, new JsonValueChangeEventArgs(child, change, key));
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,50 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
namespace System.Json
{
/// <summary>
/// An enumeration that specifies primitive and structured JavaScript Object
/// Notation (JSON) common language runtime (CLR) types.
/// </summary>
public enum JsonType
{
/// <summary>
/// Specifies the JSON string CLR type.
/// </summary>
String,
/// <summary>
/// Specifies the JSON number CLR type.
/// </summary>
Number,
/// <summary>
/// Specifies the JSON object CLR type that consists of an unordered collection
/// of key/value pairs, where the key is of type String and the value is of
/// type <see cref="System.Json.JsonValue"/>, which can, in turn, be either a
/// primitive or a structured JSON type.
/// </summary>
Object,
/// <summary>
/// Specifies the JSON array CLR type that consists of an ordered collection of
/// <see cref="System.Json.JsonValue"/>types, which can, in turn, be either
/// primitive or structured JSON types.
/// </summary>
Array,
/// <summary>
/// Specifies the JSON Boolean CLR type.
/// </summary>
Boolean,
/// <summary>
/// Specifies the type returned by calls to <see cref="System.Json.JsonValue.ValueOrDefault(string)"/>
/// or <see cref="System.Json.JsonValue.ValueOrDefault(int)"/>
/// when the element searches doesn't exist in the JSON collection. This is a special
/// value which does not represent any JSON element, and cannot be added to any
/// JSON collections.
/// </summary>
Default
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,30 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
namespace System.Json
{
/// <summary>
/// Specifies the event type when an event is raised for a <see cref="System.Json.JsonValue"/>.
/// </summary>
public enum JsonValueChange
{
/// <summary>
/// An element has been or will be added to the collection.
/// </summary>
Add,
/// <summary>
/// An element has been or will be removed from the collection.
/// </summary>
Remove,
/// <summary>
/// An element has been or will be replaced in the collection. Used on indexers.
/// </summary>
Replace,
/// <summary>
/// All elements of the collection have been or will be removed.
/// </summary>
Clear,
}
}

View File

@@ -0,0 +1,98 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
namespace System.Json
{
/// <summary>
/// Provide data for the <see cref="System.Json.JsonValue.Changing"/> and <see cref="System.Json.JsonValue.Changed"/> events.
/// </summary>
public class JsonValueChangeEventArgs : EventArgs
{
private JsonValue child;
private JsonValueChange change;
private int index;
private string key;
/// <summary>
/// Initializes a new instance of the <see cref="System.Json.JsonValueChangeEventArgs"/> class for
/// changes in a <see cref="System.Json.JsonArray"/>.
/// </summary>
/// <param name="child">The <see cref="System.Json.JsonValue"/> instance which will be or has been modified.</param>
/// <param name="change">The type of change of the <see cref="System.Json.JsonValue"/> event.</param>
/// <param name="index">The index of the element being changed in a <see cref="System.Json.JsonArray"/>.</param>
public JsonValueChangeEventArgs(JsonValue child, JsonValueChange change, int index)
{
if (index < 0)
{
throw new ArgumentOutOfRangeException("index", RS.Format(Properties.Resources.ArgumentMustBeGreaterThanOrEqualTo, index, 0));
}
this.child = child;
this.change = change;
this.index = index;
}
/// <summary>
/// Initializes a new instance of the <see cref="System.Json.JsonValueChangeEventArgs"/> class for
/// changes in a <see cref="System.Json.JsonObject"/>.
/// </summary>
/// <param name="child">The <see cref="System.Json.JsonValue"/> instance which will be or has been modified.</param>
/// <param name="change">The type of change of the <see cref="System.Json.JsonValue"/> event.</param>
/// <param name="key">The key of the element being changed in a <see cref="System.Json.JsonObject"/>.</param>
public JsonValueChangeEventArgs(JsonValue child, JsonValueChange change, string key)
{
if (change != JsonValueChange.Clear)
{
if (key == null)
{
throw new ArgumentNullException("key");
}
}
this.child = child;
this.change = change;
index = -1;
this.key = key;
}
/// <summary>
/// Gets the child which will be or has been modified.
/// </summary>
/// <remarks><p>This property is <code>null</code> for <see cref="System.Json.JsonValueChange.Clear"/> event types
/// raised by <see cref="System.Json.JsonValue"/> instances.</p>
/// <p>For <see cref="System.Json.JsonValueChange">Replace</see> events, this property contains the new value in
/// the <see cref="System.Json.JsonValue.Changing"/> event, and the old value (the one being replaced) in the
/// <see cref="System.Json.JsonValue.Changed"/> event.</p></remarks>
public JsonValue Child
{
get { return child; }
}
/// <summary>
/// Gets the type of change.
/// </summary>
public JsonValueChange Change
{
get { return change; }
}
/// <summary>
/// Gets the index in the <see cref="System.Json.JsonArray"/> where the change happened, or
/// <code>-1</code> if the change happened in a <see cref="System.Json.JsonValue"/> of a different type.
/// </summary>
public int Index
{
get { return index; }
}
/// <summary>
/// Gets the key in the <see cref="System.Json.JsonObject"/> where the change happened, or
/// <code>null</code> if the change happened in a <see cref="System.Json.JsonValue"/> of a different type.
/// </summary>
/// <remarks>This property can also be <code>null</code> if the event type is
/// <see cref="System.Json.JsonValueChange">Clear</see>.</remarks>
public string Key
{
get { return key; }
}
}
}

View File

@@ -0,0 +1,384 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
#if FEATURE_DYNAMIC
using System.Collections.Generic;
using System.Dynamic;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.Serialization.Json;
namespace System.Json
{
/// <summary>
/// This class provides dynamic behavior support for the JsonValue types.
/// </summary>
internal class JsonValueDynamicMetaObject : DynamicMetaObject
{
private static readonly MethodInfo _getValueByIndexMethodInfo = typeof(JsonValue).GetMethod("GetValue", new Type[] { typeof(int) });
private static readonly MethodInfo _getValueByKeyMethodInfo = typeof(JsonValue).GetMethod("GetValue", new Type[] { typeof(string) });
private static readonly MethodInfo _setValueByIndexMethodInfo = typeof(JsonValue).GetMethod("SetValue", new Type[] { typeof(int), typeof(object) });
private static readonly MethodInfo _setValueByKeyMethodInfo = typeof(JsonValue).GetMethod("SetValue", new Type[] { typeof(string), typeof(object) });
private static readonly MethodInfo _castValueMethodInfo = typeof(JsonValue).GetMethod("CastValue", new Type[] { typeof(JsonValue) });
private static readonly MethodInfo _changeTypeMethodInfo = typeof(Convert).GetMethod("ChangeType", new Type[] { typeof(object), typeof(Type) });
/// <summary>
/// Class constructor.
/// </summary>
/// <param name="parameter">The expression representing this <see cref="DynamicMetaObject"/> during the dynamic binding process.</param>
/// <param name="value">The runtime value represented by the <see cref="DynamicMetaObject"/>.</param>
internal JsonValueDynamicMetaObject(Expression parameter, JsonValue value)
: base(parameter, BindingRestrictions.Empty, value)
{
}
/// <summary>
/// Gets the default binding restrictions for this type.
/// </summary>
private BindingRestrictions DefaultRestrictions
{
get { return BindingRestrictions.GetTypeRestriction(Expression, LimitType); }
}
/// <summary>
/// Implements dynamic cast for JsonValue types.
/// </summary>
/// <param name="binder">An instance of the <see cref="ConvertBinder"/> that represents the details of the dynamic operation.</param>
/// <returns>The new <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
public override DynamicMetaObject BindConvert(ConvertBinder binder)
{
if (binder == null)
{
throw new ArgumentNullException("binder");
}
Expression expression = Expression;
bool implicitCastSupported =
binder.Type.IsAssignableFrom(LimitType) ||
binder.Type == typeof(IEnumerable<KeyValuePair<string, JsonValue>>) ||
binder.Type == typeof(IDynamicMetaObjectProvider) ||
binder.Type == typeof(object);
if (!implicitCastSupported)
{
if (JsonValue.IsSupportedExplicitCastType(binder.Type))
{
Expression instance = Expression.Convert(Expression, LimitType);
expression = Expression.Call(_castValueMethodInfo.MakeGenericMethod(binder.Type), new Expression[] { instance });
}
else
{
string exceptionMessage = RS.Format(Properties.Resources.CannotCastJsonValue, LimitType.FullName, binder.Type.FullName);
expression = Expression.Throw(Expression.Constant(new InvalidCastException(exceptionMessage)), typeof(object));
}
}
expression = Expression.Convert(expression, binder.Type);
return new DynamicMetaObject(expression, DefaultRestrictions);
}
/// <summary>
/// Implements setter for dynamic indexer by index (JsonArray)
/// </summary>
/// <param name="binder">An instance of the <see cref="GetIndexBinder"/> that represents the details of the dynamic operation.</param>
/// <param name="indexes">An array of <see cref="DynamicMetaObject"/> instances - indexes for the get index operation.</param>
/// <returns>The new <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
public override DynamicMetaObject BindGetIndex(GetIndexBinder binder, DynamicMetaObject[] indexes)
{
if (binder == null)
{
throw new ArgumentNullException("binder");
}
if (indexes == null)
{
throw new ArgumentNullException("indexes");
}
Expression indexExpression;
if (!JsonValueDynamicMetaObject.TryGetIndexExpression(indexes, out indexExpression))
{
return new DynamicMetaObject(indexExpression, DefaultRestrictions);
}
MethodInfo methodInfo = indexExpression.Type == typeof(string) ? _getValueByKeyMethodInfo : _getValueByIndexMethodInfo;
Expression[] args = new Expression[] { indexExpression };
return GetMethodMetaObject(methodInfo, args);
}
/// <summary>
/// Implements getter for dynamic indexer by index (JsonArray).
/// </summary>
/// <param name="binder">An instance of the <see cref="SetIndexBinder"/> that represents the details of the dynamic operation.</param>
/// <param name="indexes">An array of <see cref="DynamicMetaObject"/> instances - indexes for the set index operation.</param>
/// <param name="value">The <see cref="DynamicMetaObject"/> representing the value for the set index operation.</param>
/// <returns>The new <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
public override DynamicMetaObject BindSetIndex(SetIndexBinder binder, DynamicMetaObject[] indexes, DynamicMetaObject value)
{
if (binder == null)
{
throw new ArgumentNullException("binder");
}
if (indexes == null)
{
throw new ArgumentNullException("indexes");
}
if (value == null)
{
throw new ArgumentNullException("value");
}
Expression indexExpression;
if (!JsonValueDynamicMetaObject.TryGetIndexExpression(indexes, out indexExpression))
{
return new DynamicMetaObject(indexExpression, DefaultRestrictions);
}
MethodInfo methodInfo = indexExpression.Type == typeof(string) ? _setValueByKeyMethodInfo : _setValueByIndexMethodInfo;
Expression[] args = new Expression[] { indexExpression, Expression.Convert(value.Expression, typeof(object)) };
return GetMethodMetaObject(methodInfo, args);
}
/// <summary>
/// Implements getter for dynamic indexer by key (JsonObject).
/// </summary>
/// <param name="binder">An instance of the <see cref="GetMemberBinder"/> that represents the details of the dynamic operation.</param>
/// <returns>The new <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
public override DynamicMetaObject BindGetMember(GetMemberBinder binder)
{
if (binder == null)
{
throw new ArgumentNullException("binder");
}
PropertyInfo propInfo = LimitType.GetProperty(binder.Name, BindingFlags.Instance | BindingFlags.Public);
if (propInfo != null)
{
return base.BindGetMember(binder);
}
Expression[] args = new Expression[] { Expression.Constant(binder.Name) };
return GetMethodMetaObject(_getValueByKeyMethodInfo, args);
}
/// <summary>
/// Implements setter for dynamic indexer by key (JsonObject).
/// </summary>
/// <param name="binder">An instance of the <see cref="SetMemberBinder"/> that represents the details of the dynamic operation.</param>
/// <param name="value">The <see cref="DynamicMetaObject"/> representing the value for the set member operation.</param>
/// <returns>The new <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
public override DynamicMetaObject BindSetMember(SetMemberBinder binder, DynamicMetaObject value)
{
if (binder == null)
{
throw new ArgumentNullException("binder");
}
if (value == null)
{
throw new ArgumentNullException("value");
}
Expression[] args = new Expression[] { Expression.Constant(binder.Name), Expression.Convert(value.Expression, typeof(object)) };
return GetMethodMetaObject(_setValueByKeyMethodInfo, args);
}
/// <summary>
/// Performs the binding of the dynamic invoke member operation.
/// Implemented to support extension methods defined in <see cref="JsonValueExtensions"/> type.
/// </summary>
/// <param name="binder">An instance of the InvokeMemberBinder that represents the details of the dynamic operation.</param>
/// <param name="args">An array of DynamicMetaObject instances - arguments to the invoke member operation.</param>
/// <returns>The new DynamicMetaObject representing the result of the binding.</returns>
public override DynamicMetaObject BindInvokeMember(InvokeMemberBinder binder, DynamicMetaObject[] args)
{
if (binder == null)
{
throw new ArgumentNullException("binder");
}
if (args == null)
{
throw new ArgumentNullException("args");
}
List<Type> argTypeList = new List<Type>();
for (int idx = 0; idx < args.Length; idx++)
{
argTypeList.Add(args[idx].LimitType);
}
MethodInfo methodInfo = Value.GetType().GetMethod(binder.Name, argTypeList.ToArray());
if (methodInfo == null)
{
argTypeList.Insert(0, typeof(JsonValue));
Type[] argTypes = argTypeList.ToArray();
methodInfo = JsonValueDynamicMetaObject.GetExtensionMethod(typeof(JsonValueExtensions), binder.Name, argTypes);
if (methodInfo != null)
{
Expression thisInstance = Expression.Convert(Expression, LimitType);
Expression[] argsExpression = new Expression[argTypes.Length];
argsExpression[0] = thisInstance;
for (int i = 0; i < args.Length; i++)
{
argsExpression[i + 1] = args[i].Expression;
}
Expression callExpression = Expression.Call(methodInfo, argsExpression);
if (methodInfo.ReturnType == typeof(void))
{
callExpression = Expression.Block(callExpression, Expression.Default(binder.ReturnType));
}
else
{
callExpression = Expression.Convert(Expression.Call(methodInfo, argsExpression), binder.ReturnType);
}
return new DynamicMetaObject(callExpression, DefaultRestrictions);
}
}
return base.BindInvokeMember(binder, args);
}
/// <summary>
/// Returns the enumeration of all dynamic member names.
/// </summary>
/// <returns>An <see cref="IEnumerable{T}"/> of string reprenseting the dynamic member names.</returns>
public override IEnumerable<string> GetDynamicMemberNames()
{
JsonValue jsonValue = Value as JsonValue;
if (jsonValue != null)
{
List<string> names = new List<string>();
foreach (KeyValuePair<string, JsonValue> pair in jsonValue)
{
names.Add(pair.Key);
}
return names;
}
return base.GetDynamicMemberNames();
}
/// <summary>
/// Gets a <see cref="MethodInfo"/> instance for the specified method name in the specified type.
/// </summary>
/// <param name="extensionProviderType">The extension provider type.</param>
/// <param name="methodName">The name of the method to get the info for.</param>
/// <param name="argTypes">The types of the method arguments.</param>
/// <returns>A <see cref="MethodInfo"/>instance or null if the method cannot be resolved.</returns>
private static MethodInfo GetExtensionMethod(Type extensionProviderType, string methodName, Type[] argTypes)
{
MethodInfo methodInfo = null;
MethodInfo[] methods = extensionProviderType.GetMethods();
foreach (MethodInfo info in methods)
{
if (info.Name == methodName)
{
methodInfo = info;
if (!info.IsGenericMethodDefinition)
{
bool paramsMatch = true;
ParameterInfo[] args = methodInfo.GetParameters();
if (args.Length == argTypes.Length)
{
for (int idx = 0; idx < args.Length; idx++)
{
if (!args[idx].ParameterType.IsAssignableFrom(argTypes[idx]))
{
paramsMatch = false;
break;
}
}
if (paramsMatch)
{
break;
}
}
}
}
}
return methodInfo;
}
/// <summary>
/// Attempts to get an expression for an index parameter.
/// </summary>
/// <param name="indexes">The operation indexes parameter.</param>
/// <param name="expression">A <see cref="Expression"/> to be initialized to the index expression if the operation is successful, otherwise an error expression.</param>
/// <returns>true the operation is successful, false otherwise.</returns>
private static bool TryGetIndexExpression(DynamicMetaObject[] indexes, out Expression expression)
{
if (indexes.Length == 1 && indexes[0] != null && indexes[0].Value != null)
{
DynamicMetaObject index = indexes[0];
Type indexType = indexes[0].Value.GetType();
switch (Type.GetTypeCode(indexType))
{
case TypeCode.Char:
case TypeCode.Int16:
case TypeCode.UInt16:
case TypeCode.Byte:
case TypeCode.SByte:
Expression argExp = Expression.Convert(index.Expression, typeof(object));
Expression typeExp = Expression.Constant(typeof(int));
expression = Expression.Convert(Expression.Call(_changeTypeMethodInfo, new Expression[] { argExp, typeExp }), typeof(int));
return true;
case TypeCode.Int32:
case TypeCode.String:
expression = index.Expression;
return true;
}
expression = Expression.Throw(Expression.Constant(new ArgumentException(RS.Format(Properties.Resources.InvalidIndexType, indexType))), typeof(object));
return false;
}
expression = Expression.Throw(Expression.Constant(new ArgumentException(Properties.Resources.NonSingleNonNullIndexNotSupported)), typeof(object));
return false;
}
/// <summary>
/// Gets a <see cref="DynamicMetaObject"/> for a method call.
/// </summary>
/// <param name="methodInfo">Info for the method to be performed.</param>
/// <param name="args">expression array representing the method arguments</param>
/// <returns>A meta object for the method call.</returns>
private DynamicMetaObject GetMethodMetaObject(MethodInfo methodInfo, Expression[] args)
{
Expression instance = Expression.Convert(Expression, LimitType);
Expression methodCall = Expression.Call(instance, methodInfo, args);
BindingRestrictions restrictions = DefaultRestrictions;
DynamicMetaObject metaObj = new DynamicMetaObject(methodCall, restrictions);
return metaObj;
}
}
}
#endif

View File

@@ -0,0 +1,37 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
namespace System.Json
{
/// <summary>
/// This class extends the funcionality of the <see cref="JsonValue"/> type for better Linq support .
/// </summary>
[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Justification = "Linq is a technical name.")]
[EditorBrowsable(EditorBrowsableState.Never)]
public static class JsonValueLinqExtensions
{
/// <summary>
/// Extension method for creating a <see cref="JsonValue"/> from an <see cref="IEnumerable{T}"/> collection of <see cref="JsonValue"/> types.
/// </summary>
/// <param name="items">The enumerable instance.</param>
/// <returns>A <see cref="JsonArray"/> created from the specified items.</returns>
public static JsonArray ToJsonArray(this IEnumerable<JsonValue> items)
{
return new JsonArray(items);
}
/// <summary>
/// Extension method for creating a <see cref="JsonValue"/> from an <see cref="IEnumerable{T}"/> collection of <see cref="KeyValuePair{K,V}"/> of <see cref="String"/> and <see cref="JsonValue"/> types.
/// </summary>
/// <param name="items">The enumerable instance.</param>
/// <returns>A <see cref="JsonValue"/> created from the specified items.</returns>
[SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "JsonValue implements the nested type in param.")]
public static JsonObject ToJsonObject(this IEnumerable<KeyValuePair<string, JsonValue>> items)
{
return new JsonObject(items);
}
}
}

View File

@@ -0,0 +1,48 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
namespace System.Json
{
/// <summary>
/// Struct that wraps values which cause JIT compilation at runtime.
/// This Struct is added to solve the FxCop warning CA908 in JsonObject.cs.
/// </summary>
/// <typeparam name="T">Wrapped type.</typeparam>
internal struct NGenWrapper<T>
{
/// <summary>
/// Value of type T which represents the actual data which is currently in hold.
/// </summary>
public T Value;
/// <summary>
/// Creates an instance of the <see cref="System.Json.NGenWrapper{T}"/> class
/// </summary>
/// <param name="value">The wrapped object of T</param>
public NGenWrapper(T value)
{
Value = value;
}
/// <summary>
/// Cast operator from <see cref="System.Json.NGenWrapper{T}"/> to <typeparamref name="T"/>
/// </summary>
/// <param name="value">Object in type <see cref="System.Json.NGenWrapper{T}"/></param>
/// <returns>Object in type <typeparamref name="T">The wrapped element type</typeparamref></returns>
/// <typeparamref name="T">The wrapped element type</typeparamref>
public static implicit operator T(NGenWrapper<T> value)
{
return value.Value;
}
/// <summary>
/// Cast operator from <typeparamref name="T"/> to <see cref="System.Json.NGenWrapper{T}"/>
/// </summary>
/// <param name="value">Object in type <typeparamref name="T"/></param>
/// <returns>Object in type <see cref="System.Json.NGenWrapper{T}"/></returns>
/// <typeparamref name="T">The wrapped element type</typeparamref>
public static implicit operator NGenWrapper<T>(T value)
{
return new NGenWrapper<T>(value);
}
}
}

View File

@@ -0,0 +1,12 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Reflection;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("System.Json")]
[assembly: AssemblyDescription("")]
[assembly: Guid("6fd72360-ebfc-4097-96fa-2ee418c04f7b")]

Some files were not shown because too many files have changed in this diff Show More