GeoJam2021/Assets/UserReporting/Scripts/Plugin/SimpleJson.cs
2021-07-23 09:45:12 +02:00

2156 lines
80 KiB
C#

//-----------------------------------------------------------------------
// <copyright file="SimpleJson.cs" company="The Outercurve Foundation">
// Copyright (c) 2011, The Outercurve Foundation.
//
// Licensed under the MIT License (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.opensource.org/licenses/mit-license.php
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
// <author>Nathan Totten (ntotten.com), Jim Zimmerman (jimzimmerman.com) and Prabir Shrestha (prabir.me)</author>
// <website>https://github.com/facebook-csharp-sdk/simple-json</website>
//-----------------------------------------------------------------------
// VERSION:
// NOTE: uncomment the following line to make SimpleJson class internal.
//#define SIMPLE_JSON_INTERNAL
// NOTE: uncomment the following line to make JsonArray and JsonObject class internal.
//#define SIMPLE_JSON_OBJARRAYINTERNAL
// NOTE: uncomment the following line to enable dynamic support.
//#define SIMPLE_JSON_DYNAMIC
// NOTE: uncomment the following line to enable DataContract support.
//#define SIMPLE_JSON_DATACONTRACT
// NOTE: uncomment the following line to enable IReadOnlyCollection<T> and IReadOnlyList<T> support.
//#define SIMPLE_JSON_READONLY_COLLECTIONS
// NOTE: uncomment the following line to disable linq expressions/compiled lambda (better performance) instead of method.invoke().
// define if you are using .net framework <= 3.0 or < WP7.5
#define SIMPLE_JSON_NO_LINQ_EXPRESSION
// NOTE: uncomment the following line if you are compiling under Window Metro style application/library.
// usually already defined in properties
//#define NETFX_CORE;
// If you are targetting WinStore, WP8 and NET4.5+ PCL make sure to #define SIMPLE_JSON_TYPEINFO;
// original json parsing code from http://techblog.procurios.nl/k/618/news/view/14605/14863/How-do-I-write-my-own-parser-for-JSON.html
#if NETFX_CORE
#define SIMPLE_JSON_TYPEINFO
#endif
using System;
using System.CodeDom.Compiler;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Reflection;
using System.Runtime.Serialization;
using System.Text;
using Unity.Cloud.UserReporting.Plugin.SimpleJson.Reflection;
#if !SIMPLE_JSON_NO_LINQ_EXPRESSION
using System.Linq.Expressions;
#endif
#if SIMPLE_JSON_DYNAMIC
using System.Dynamic;
#endif
// ReSharper disable LoopCanBeConvertedToQuery
// ReSharper disable RedundantExplicitArrayCreation
// ReSharper disable SuggestUseVarKeywordEvident
namespace Unity.Cloud.UserReporting.Plugin.SimpleJson
{
[GeneratedCode("simple-json", "1.0.0")]
[EditorBrowsable(EditorBrowsableState.Never)]
[SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix")]
#if SIMPLE_JSON_OBJARRAYINTERNAL
internal
#else
public
#endif
class JsonArray : List<object>
{
public JsonArray()
{
}
public JsonArray(int capacity) : base(capacity)
{
}
public override string ToString()
{
return SimpleJson.SerializeObject(this) ?? string.Empty;
}
}
[GeneratedCode("simple-json", "1.0.0")]
[EditorBrowsable(EditorBrowsableState.Never)]
[SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix")]
#if SIMPLE_JSON_OBJARRAYINTERNAL
internal
#else
public
#endif
class JsonObject :
#if SIMPLE_JSON_DYNAMIC
DynamicObject,
#endif
IDictionary<string, object>
{
private readonly Dictionary<string, object> _members;
public JsonObject()
{
_members = new Dictionary<string, object>();
}
public JsonObject(IEqualityComparer<string> comparer)
{
_members = new Dictionary<string, object>(comparer);
}
public object this[int index]
{
get { return JsonObject.GetAtIndex(_members, index); }
}
internal static object GetAtIndex(IDictionary<string, object> obj, int index)
{
if (obj == null)
{
throw new ArgumentNullException("obj");
}
if (index >= obj.Count)
{
throw new ArgumentOutOfRangeException("index");
}
int i = 0;
foreach (KeyValuePair<string, object> o in obj)
{
if (i++ == index)
{
return o.Value;
}
}
return null;
}
public void Add(string key, object value)
{
_members.Add(key, value);
}
public bool ContainsKey(string key)
{
return _members.ContainsKey(key);
}
public ICollection<string> Keys
{
get { return _members.Keys; }
}
public bool Remove(string key)
{
return _members.Remove(key);
}
public bool TryGetValue(string key, out object value)
{
return _members.TryGetValue(key, out value);
}
public ICollection<object> Values
{
get { return _members.Values; }
}
public object this[string key]
{
get { return _members[key]; }
set { _members[key] = value; }
}
public void Add(KeyValuePair<string, object> item)
{
_members.Add(item.Key, item.Value);
}
public void Clear()
{
_members.Clear();
}
public bool Contains(KeyValuePair<string, object> item)
{
return _members.ContainsKey(item.Key) && this._members[item.Key] == item.Value;
}
public void CopyTo(KeyValuePair<string, object>[] array, int arrayIndex)
{
if (array == null)
{
throw new ArgumentNullException("array");
}
int num = Count;
foreach (KeyValuePair<string, object> kvp in this)
{
array[arrayIndex++] = kvp;
if (--num <= 0)
{
return;
}
}
}
public int Count
{
get { return _members.Count; }
}
public bool IsReadOnly
{
get { return false; }
}
public bool Remove(KeyValuePair<string, object> item)
{
return _members.Remove(item.Key);
}
public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
{
return _members.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return _members.GetEnumerator();
}
public override string ToString()
{
return SimpleJson.SerializeObject(this);
}
#if SIMPLE_JSON_DYNAMIC
public override bool TryConvert(ConvertBinder binder, out object result)
{
// <pex>
if (binder == null)
throw new ArgumentNullException("binder");
// </pex>
Type targetType = binder.Type;
if ((targetType == typeof(IEnumerable)) ||
(targetType == typeof(IEnumerable<KeyValuePair<string, object>>)) ||
(targetType == typeof(IDictionary<string, object>)) ||
(targetType == typeof(IDictionary)))
{
result = this;
return true;
}
return base.TryConvert(binder, out result);
}
public override bool TryDeleteMember(DeleteMemberBinder binder)
{
// <pex>
if (binder == null)
throw new ArgumentNullException("binder");
// </pex>
return _members.Remove(binder.Name);
}
public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result)
{
if (indexes == null) throw new ArgumentNullException("indexes");
if (indexes.Length == 1)
{
result = ((IDictionary<string, object>)this)[(string)indexes[0]];
return true;
}
result = null;
return true;
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
object value;
if (_members.TryGetValue(binder.Name, out value))
{
result = value;
return true;
}
result = null;
return true;
}
public override bool TrySetIndex(SetIndexBinder binder, object[] indexes, object value)
{
if (indexes == null) throw new ArgumentNullException("indexes");
if (indexes.Length == 1)
{
((IDictionary<string, object>)this)[(string)indexes[0]] = value;
return true;
}
return base.TrySetIndex(binder, indexes, value);
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
// <pex>
if (binder == null)
throw new ArgumentNullException("binder");
// </pex>
_members[binder.Name] = value;
return true;
}
public override IEnumerable<string> GetDynamicMemberNames()
{
foreach (var key in Keys)
yield return key;
}
#endif
}
}
namespace Unity.Cloud.UserReporting.Plugin.SimpleJson
{
[GeneratedCode("simple-json", "1.0.0")]
#if SIMPLE_JSON_INTERNAL
internal
#else
public
#endif
static class SimpleJson
{
private const int TOKEN_NONE = 0;
private const int TOKEN_CURLY_OPEN = 1;
private const int TOKEN_CURLY_CLOSE = 2;
private const int TOKEN_SQUARED_OPEN = 3;
private const int TOKEN_SQUARED_CLOSE = 4;
private const int TOKEN_COLON = 5;
private const int TOKEN_COMMA = 6;
private const int TOKEN_STRING = 7;
private const int TOKEN_NUMBER = 8;
private const int TOKEN_TRUE = 9;
private const int TOKEN_FALSE = 10;
private const int TOKEN_NULL = 11;
private const int BUILDER_CAPACITY = 2000;
private static readonly char[] EscapeTable;
private static readonly char[] EscapeCharacters = new char[] {'"', '\\', '\b', '\f', '\n', '\r', '\t'};
static SimpleJson()
{
SimpleJson.EscapeTable = new char[93];
SimpleJson.EscapeTable['"'] = '"';
SimpleJson.EscapeTable['\\'] = '\\';
SimpleJson.EscapeTable['\b'] = 'b';
SimpleJson.EscapeTable['\f'] = 'f';
SimpleJson.EscapeTable['\n'] = 'n';
SimpleJson.EscapeTable['\r'] = 'r';
SimpleJson.EscapeTable['\t'] = 't';
}
public static object DeserializeObject(string json)
{
object obj;
if (SimpleJson.TryDeserializeObject(json, out obj))
{
return obj;
}
throw new SerializationException("Invalid JSON string");
}
[SuppressMessage("Microsoft.Design", "CA1007:UseGenericsWhereAppropriate", Justification = "Need to support .NET 2")]
public static bool TryDeserializeObject(string json, out object obj)
{
bool success = true;
if (json != null)
{
char[] charArray = json.ToCharArray();
int index = 0;
obj = SimpleJson.ParseValue(charArray, ref index, ref success);
}
else
{
obj = null;
}
return success;
}
public static object DeserializeObject(string json, Type type, IJsonSerializerStrategy jsonSerializerStrategy)
{
object jsonObject = SimpleJson.DeserializeObject(json);
return type == null || jsonObject != null && ReflectionUtils.IsAssignableFrom(jsonObject.GetType(), type) ? jsonObject : (jsonSerializerStrategy ?? SimpleJson.CurrentJsonSerializerStrategy).DeserializeObject(jsonObject, type);
}
public static object DeserializeObject(string json, Type type)
{
return SimpleJson.DeserializeObject(json, type, null);
}
public static T DeserializeObject<T>(string json, IJsonSerializerStrategy jsonSerializerStrategy)
{
return (T) SimpleJson.DeserializeObject(json, typeof(T), jsonSerializerStrategy);
}
public static T DeserializeObject<T>(string json)
{
return (T) SimpleJson.DeserializeObject(json, typeof(T), null);
}
public static string SerializeObject(object json, IJsonSerializerStrategy jsonSerializerStrategy)
{
StringBuilder builder = new StringBuilder(SimpleJson.BUILDER_CAPACITY);
bool success = SimpleJson.SerializeValue(jsonSerializerStrategy, json, builder);
return success ? builder.ToString() : null;
}
public static string SerializeObject(object json)
{
return SimpleJson.SerializeObject(json, SimpleJson.CurrentJsonSerializerStrategy);
}
public static string EscapeToJavascriptString(string jsonString)
{
if (string.IsNullOrEmpty(jsonString))
{
return jsonString;
}
StringBuilder sb = new StringBuilder();
char c;
for (int i = 0; i < jsonString.Length;)
{
c = jsonString[i++];
if (c == '\\')
{
int remainingLength = jsonString.Length - i;
if (remainingLength >= 2)
{
char lookahead = jsonString[i];
if (lookahead == '\\')
{
sb.Append('\\');
++i;
}
else if (lookahead == '"')
{
sb.Append("\"");
++i;
}
else if (lookahead == 't')
{
sb.Append('\t');
++i;
}
else if (lookahead == 'b')
{
sb.Append('\b');
++i;
}
else if (lookahead == 'n')
{
sb.Append('\n');
++i;
}
else if (lookahead == 'r')
{
sb.Append('\r');
++i;
}
}
}
else
{
sb.Append(c);
}
}
return sb.ToString();
}
private static IDictionary<string, object> ParseObject(char[] json, ref int index, ref bool success)
{
IDictionary<string, object> table = new JsonObject();
int token;
// {
SimpleJson.NextToken(json, ref index);
bool done = false;
while (!done)
{
token = SimpleJson.LookAhead(json, index);
if (token == SimpleJson.TOKEN_NONE)
{
success = false;
return null;
}
else if (token == SimpleJson.TOKEN_COMMA)
{
SimpleJson.NextToken(json, ref index);
}
else if (token == SimpleJson.TOKEN_CURLY_CLOSE)
{
SimpleJson.NextToken(json, ref index);
return table;
}
else
{
// name
string name = SimpleJson.ParseString(json, ref index, ref success);
if (!success)
{
success = false;
return null;
}
// :
token = SimpleJson.NextToken(json, ref index);
if (token != SimpleJson.TOKEN_COLON)
{
success = false;
return null;
}
// value
object value = SimpleJson.ParseValue(json, ref index, ref success);
if (!success)
{
success = false;
return null;
}
table[name] = value;
}
}
return table;
}
private static JsonArray ParseArray(char[] json, ref int index, ref bool success)
{
JsonArray array = new JsonArray();
// [
SimpleJson.NextToken(json, ref index);
bool done = false;
while (!done)
{
int token = SimpleJson.LookAhead(json, index);
if (token == SimpleJson.TOKEN_NONE)
{
success = false;
return null;
}
else if (token == SimpleJson.TOKEN_COMMA)
{
SimpleJson.NextToken(json, ref index);
}
else if (token == SimpleJson.TOKEN_SQUARED_CLOSE)
{
SimpleJson.NextToken(json, ref index);
break;
}
else
{
object value = SimpleJson.ParseValue(json, ref index, ref success);
if (!success)
{
return null;
}
array.Add(value);
}
}
return array;
}
private static object ParseValue(char[] json, ref int index, ref bool success)
{
switch (SimpleJson.LookAhead(json, index))
{
case SimpleJson.TOKEN_STRING: return SimpleJson.ParseString(json, ref index, ref success);
case SimpleJson.TOKEN_NUMBER: return SimpleJson.ParseNumber(json, ref index, ref success);
case SimpleJson.TOKEN_CURLY_OPEN: return SimpleJson.ParseObject(json, ref index, ref success);
case SimpleJson.TOKEN_SQUARED_OPEN: return SimpleJson.ParseArray(json, ref index, ref success);
case SimpleJson.TOKEN_TRUE:
SimpleJson.NextToken(json, ref index);
return true;
case SimpleJson.TOKEN_FALSE:
SimpleJson.NextToken(json, ref index);
return false;
case SimpleJson.TOKEN_NULL:
SimpleJson.NextToken(json, ref index);
return null;
case SimpleJson.TOKEN_NONE: break;
}
success = false;
return null;
}
private static string ParseString(char[] json, ref int index, ref bool success)
{
StringBuilder s = new StringBuilder(SimpleJson.BUILDER_CAPACITY);
char c;
SimpleJson.EatWhitespace(json, ref index);
// "
c = json[index++];
bool complete = false;
while (!complete)
{
if (index == json.Length)
{
break;
}
c = json[index++];
if (c == '"')
{
complete = true;
break;
}
else if (c == '\\')
{
if (index == json.Length)
{
break;
}
c = json[index++];
if (c == '"')
{
s.Append('"');
}
else if (c == '\\')
{
s.Append('\\');
}
else if (c == '/')
{
s.Append('/');
}
else if (c == 'b')
{
s.Append('\b');
}
else if (c == 'f')
{
s.Append('\f');
}
else if (c == 'n')
{
s.Append('\n');
}
else if (c == 'r')
{
s.Append('\r');
}
else if (c == 't')
{
s.Append('\t');
}
else if (c == 'u')
{
int remainingLength = json.Length - index;
if (remainingLength >= 4)
{
// parse the 32 bit hex into an integer codepoint
uint codePoint;
if (!(success = UInt32.TryParse(new string(json, index, 4), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out codePoint)))
{
return "";
}
// convert the integer codepoint to a unicode char and add to string
if (0xD800 <= codePoint && codePoint <= 0xDBFF) // if high surrogate
{
index += 4; // skip 4 chars
remainingLength = json.Length - index;
if (remainingLength >= 6)
{
uint lowCodePoint;
if (new string(json, index, 2) == "\\u" && UInt32.TryParse(new string(json, index + 2, 4), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out lowCodePoint))
{
if (0xDC00 <= lowCodePoint && lowCodePoint <= 0xDFFF) // if low surrogate
{
s.Append((char) codePoint);
s.Append((char) lowCodePoint);
index += 6; // skip 6 chars
continue;
}
}
}
success = false; // invalid surrogate pair
return "";
}
s.Append(SimpleJson.ConvertFromUtf32((int) codePoint));
// skip 4 chars
index += 4;
}
else
{
break;
}
}
}
else
{
s.Append(c);
}
}
if (!complete)
{
success = false;
return null;
}
return s.ToString();
}
private static string ConvertFromUtf32(int utf32)
{
// http://www.java2s.com/Open-Source/CSharp/2.6.4-mono-.net-core/System/System/Char.cs.htm
if (utf32 < 0 || utf32 > 0x10FFFF)
{
throw new ArgumentOutOfRangeException("utf32", "The argument must be from 0 to 0x10FFFF.");
}
if (0xD800 <= utf32 && utf32 <= 0xDFFF)
{
throw new ArgumentOutOfRangeException("utf32", "The argument must not be in surrogate pair range.");
}
if (utf32 < 0x10000)
{
return new string((char) utf32, 1);
}
utf32 -= 0x10000;
return new string(new char[] {(char) ((utf32 >> 10) + 0xD800), (char) (utf32 % 0x0400 + 0xDC00)});
}
private static object ParseNumber(char[] json, ref int index, ref bool success)
{
SimpleJson.EatWhitespace(json, ref index);
int lastIndex = SimpleJson.GetLastIndexOfNumber(json, index);
int charLength = lastIndex - index + 1;
object returnNumber;
string str = new string(json, index, charLength);
if (str.IndexOf(".", StringComparison.OrdinalIgnoreCase) != -1 || str.IndexOf("e", StringComparison.OrdinalIgnoreCase) != -1)
{
double number;
success = double.TryParse(new string(json, index, charLength), NumberStyles.Any, CultureInfo.InvariantCulture, out number);
returnNumber = number;
}
else
{
long number;
success = long.TryParse(new string(json, index, charLength), NumberStyles.Any, CultureInfo.InvariantCulture, out number);
returnNumber = number;
}
index = lastIndex + 1;
return returnNumber;
}
private static int GetLastIndexOfNumber(char[] json, int index)
{
int lastIndex;
for (lastIndex = index; lastIndex < json.Length; lastIndex++)
{
if ("0123456789+-.eE".IndexOf(json[lastIndex]) == -1)
{
break;
}
}
return lastIndex - 1;
}
private static void EatWhitespace(char[] json, ref int index)
{
for (; index < json.Length; index++)
{
if (" \t\n\r\b\f".IndexOf(json[index]) == -1)
{
break;
}
}
}
private static int LookAhead(char[] json, int index)
{
int saveIndex = index;
return SimpleJson.NextToken(json, ref saveIndex);
}
[SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
private static int NextToken(char[] json, ref int index)
{
SimpleJson.EatWhitespace(json, ref index);
if (index == json.Length)
{
return SimpleJson.TOKEN_NONE;
}
char c = json[index];
index++;
switch (c)
{
case '{': return SimpleJson.TOKEN_CURLY_OPEN;
case '}': return SimpleJson.TOKEN_CURLY_CLOSE;
case '[': return SimpleJson.TOKEN_SQUARED_OPEN;
case ']': return SimpleJson.TOKEN_SQUARED_CLOSE;
case ',': return SimpleJson.TOKEN_COMMA;
case '"': return SimpleJson.TOKEN_STRING;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '-': return SimpleJson.TOKEN_NUMBER;
case ':': return SimpleJson.TOKEN_COLON;
}
index--;
int remainingLength = json.Length - index;
// false
if (remainingLength >= 5)
{
if (json[index] == 'f' && json[index + 1] == 'a' && json[index + 2] == 'l' && json[index + 3] == 's' && json[index + 4] == 'e')
{
index += 5;
return SimpleJson.TOKEN_FALSE;
}
}
// true
if (remainingLength >= 4)
{
if (json[index] == 't' && json[index + 1] == 'r' && json[index + 2] == 'u' && json[index + 3] == 'e')
{
index += 4;
return SimpleJson.TOKEN_TRUE;
}
}
// null
if (remainingLength >= 4)
{
if (json[index] == 'n' && json[index + 1] == 'u' && json[index + 2] == 'l' && json[index + 3] == 'l')
{
index += 4;
return SimpleJson.TOKEN_NULL;
}
}
return SimpleJson.TOKEN_NONE;
}
private static bool SerializeValue(IJsonSerializerStrategy jsonSerializerStrategy, object value, StringBuilder builder)
{
bool success = true;
string stringValue = value as string;
if (stringValue != null)
{
success = SimpleJson.SerializeString(stringValue, builder);
}
else
{
IDictionary<string, object> dict = value as IDictionary<string, object>;
if (dict != null)
{
success = SimpleJson.SerializeObject(jsonSerializerStrategy, dict.Keys, dict.Values, builder);
}
else
{
IDictionary<string, string> stringDictionary = value as IDictionary<string, string>;
if (stringDictionary != null)
{
success = SimpleJson.SerializeObject(jsonSerializerStrategy, stringDictionary.Keys, stringDictionary.Values, builder);
}
else
{
IEnumerable enumerableValue = value as IEnumerable;
if (enumerableValue != null)
{
success = SimpleJson.SerializeArray(jsonSerializerStrategy, enumerableValue, builder);
}
else if (SimpleJson.IsNumeric(value))
{
success = SimpleJson.SerializeNumber(value, builder);
}
else if (value is bool)
{
builder.Append((bool) value ? "true" : "false");
}
else if (value == null)
{
builder.Append("null");
}
else
{
object serializedObject;
success = jsonSerializerStrategy.TrySerializeNonPrimitiveObject(value, out serializedObject);
if (success)
{
SimpleJson.SerializeValue(jsonSerializerStrategy, serializedObject, builder);
}
}
}
}
}
return success;
}
private static bool SerializeObject(IJsonSerializerStrategy jsonSerializerStrategy, IEnumerable keys, IEnumerable values, StringBuilder builder)
{
builder.Append("{");
IEnumerator ke = keys.GetEnumerator();
IEnumerator ve = values.GetEnumerator();
bool first = true;
while (ke.MoveNext() && ve.MoveNext())
{
object key = ke.Current;
object value = ve.Current;
if (!first)
{
builder.Append(",");
}
string stringKey = key as string;
if (stringKey != null)
{
SimpleJson.SerializeString(stringKey, builder);
}
else if (!SimpleJson.SerializeValue(jsonSerializerStrategy, value, builder))
{
return false;
}
builder.Append(":");
if (!SimpleJson.SerializeValue(jsonSerializerStrategy, value, builder))
{
return false;
}
first = false;
}
builder.Append("}");
return true;
}
private static bool SerializeArray(IJsonSerializerStrategy jsonSerializerStrategy, IEnumerable anArray, StringBuilder builder)
{
builder.Append("[");
bool first = true;
foreach (object value in anArray)
{
if (!first)
{
builder.Append(",");
}
if (!SimpleJson.SerializeValue(jsonSerializerStrategy, value, builder))
{
return false;
}
first = false;
}
builder.Append("]");
return true;
}
private static bool SerializeString(string aString, StringBuilder builder)
{
// Happy path if there's nothing to be escaped. IndexOfAny is highly optimized (and unmanaged)
if (aString.IndexOfAny(SimpleJson.EscapeCharacters) == -1)
{
builder.Append('"');
builder.Append(aString);
builder.Append('"');
return true;
}
builder.Append('"');
int safeCharacterCount = 0;
char[] charArray = aString.ToCharArray();
for (int i = 0; i < charArray.Length; i++)
{
char c = charArray[i];
// Non ascii characters are fine, buffer them up and send them to the builder
// in larger chunks if possible. The escape table is a 1:1 translation table
// with \0 [default(char)] denoting a safe character.
if (c >= SimpleJson.EscapeTable.Length || SimpleJson.EscapeTable[c] == default(char))
{
safeCharacterCount++;
}
else
{
if (safeCharacterCount > 0)
{
builder.Append(charArray, i - safeCharacterCount, safeCharacterCount);
safeCharacterCount = 0;
}
builder.Append('\\');
builder.Append(SimpleJson.EscapeTable[c]);
}
}
if (safeCharacterCount > 0)
{
builder.Append(charArray, charArray.Length - safeCharacterCount, safeCharacterCount);
}
builder.Append('"');
return true;
}
private static bool SerializeNumber(object number, StringBuilder builder)
{
if (number is long)
{
builder.Append(((long) number).ToString(CultureInfo.InvariantCulture));
}
else if (number is ulong)
{
builder.Append(((ulong) number).ToString(CultureInfo.InvariantCulture));
}
else if (number is int)
{
builder.Append(((int) number).ToString(CultureInfo.InvariantCulture));
}
else if (number is uint)
{
builder.Append(((uint) number).ToString(CultureInfo.InvariantCulture));
}
else if (number is decimal)
{
builder.Append(((decimal) number).ToString(CultureInfo.InvariantCulture));
}
else if (number is float)
{
builder.Append(((float) number).ToString(CultureInfo.InvariantCulture));
}
else
{
builder.Append(Convert.ToDouble(number, CultureInfo.InvariantCulture)
.ToString("r", CultureInfo.InvariantCulture));
}
return true;
}
private static bool IsNumeric(object value)
{
if (value is sbyte)
{
return true;
}
if (value is byte)
{
return true;
}
if (value is short)
{
return true;
}
if (value is ushort)
{
return true;
}
if (value is int)
{
return true;
}
if (value is uint)
{
return true;
}
if (value is long)
{
return true;
}
if (value is ulong)
{
return true;
}
if (value is float)
{
return true;
}
if (value is double)
{
return true;
}
if (value is decimal)
{
return true;
}
return false;
}
private static IJsonSerializerStrategy _currentJsonSerializerStrategy;
public static IJsonSerializerStrategy CurrentJsonSerializerStrategy
{
get
{
return SimpleJson._currentJsonSerializerStrategy ?? (SimpleJson._currentJsonSerializerStrategy =
#if SIMPLE_JSON_DATACONTRACT
DataContractJsonSerializerStrategy
#else
SimpleJson.PocoJsonSerializerStrategy
#endif
);
}
set { SimpleJson._currentJsonSerializerStrategy = value; }
}
private static PocoJsonSerializerStrategy _pocoJsonSerializerStrategy;
[EditorBrowsable(EditorBrowsableState.Advanced)]
public static PocoJsonSerializerStrategy PocoJsonSerializerStrategy
{
get { return SimpleJson._pocoJsonSerializerStrategy ?? (SimpleJson._pocoJsonSerializerStrategy = new PocoJsonSerializerStrategy()); }
}
#if SIMPLE_JSON_DATACONTRACT
private static DataContractJsonSerializerStrategy _dataContractJsonSerializerStrategy;
[System.ComponentModel.EditorBrowsable(EditorBrowsableState.Advanced)]
public static DataContractJsonSerializerStrategy DataContractJsonSerializerStrategy
{
get
{
return _dataContractJsonSerializerStrategy ?? (_dataContractJsonSerializerStrategy = new DataContractJsonSerializerStrategy());
}
}
#endif
}
[GeneratedCode("simple-json", "1.0.0")]
#if SIMPLE_JSON_INTERNAL
internal
#else
public
#endif
interface IJsonSerializerStrategy
{
[SuppressMessage("Microsoft.Design", "CA1007:UseGenericsWhereAppropriate", Justification = "Need to support .NET 2")]
bool TrySerializeNonPrimitiveObject(object input, out object output);
object DeserializeObject(object value, Type type);
}
[GeneratedCode("simple-json", "1.0.0")]
#if SIMPLE_JSON_INTERNAL
internal
#else
public
#endif
class PocoJsonSerializerStrategy : IJsonSerializerStrategy
{
internal IDictionary<Type, ReflectionUtils.ConstructorDelegate> ConstructorCache;
internal IDictionary<Type, IDictionary<string, ReflectionUtils.GetDelegate>> GetCache;
internal IDictionary<Type, IDictionary<string, KeyValuePair<Type, ReflectionUtils.SetDelegate>>> SetCache;
internal static readonly Type[] EmptyTypes = new Type[0];
internal static readonly Type[] ArrayConstructorParameterTypes = new Type[] {typeof(int)};
private static readonly string[] Iso8601Format = new string[] {@"yyyy-MM-dd\THH:mm:ss.FFFFFFF\Z", @"yyyy-MM-dd\THH:mm:ss\Z", @"yyyy-MM-dd\THH:mm:ssK"};
public PocoJsonSerializerStrategy()
{
ConstructorCache = new ReflectionUtils.ThreadSafeDictionary<Type, ReflectionUtils.ConstructorDelegate>(ContructorDelegateFactory);
GetCache = new ReflectionUtils.ThreadSafeDictionary<Type, IDictionary<string, ReflectionUtils.GetDelegate>>(GetterValueFactory);
SetCache = new ReflectionUtils.ThreadSafeDictionary<Type, IDictionary<string, KeyValuePair<Type, ReflectionUtils.SetDelegate>>>(SetterValueFactory);
}
protected virtual string MapClrMemberNameToJsonFieldName(string clrPropertyName)
{
return clrPropertyName;
}
internal virtual ReflectionUtils.ConstructorDelegate ContructorDelegateFactory(Type key)
{
return ReflectionUtils.GetContructor(key, key.IsArray ? PocoJsonSerializerStrategy.ArrayConstructorParameterTypes : PocoJsonSerializerStrategy.EmptyTypes);
}
internal virtual IDictionary<string, ReflectionUtils.GetDelegate> GetterValueFactory(Type type)
{
IDictionary<string, ReflectionUtils.GetDelegate> result = new Dictionary<string, ReflectionUtils.GetDelegate>();
foreach (PropertyInfo propertyInfo in ReflectionUtils.GetProperties(type))
{
if (propertyInfo.CanRead)
{
MethodInfo getMethod = ReflectionUtils.GetGetterMethodInfo(propertyInfo);
if (getMethod.IsStatic || !getMethod.IsPublic)
{
continue;
}
result[MapClrMemberNameToJsonFieldName(propertyInfo.Name)] = ReflectionUtils.GetGetMethod(propertyInfo);
}
}
foreach (FieldInfo fieldInfo in ReflectionUtils.GetFields(type))
{
if (fieldInfo.IsStatic || !fieldInfo.IsPublic)
{
continue;
}
result[MapClrMemberNameToJsonFieldName(fieldInfo.Name)] = ReflectionUtils.GetGetMethod(fieldInfo);
}
return result;
}
internal virtual IDictionary<string, KeyValuePair<Type, ReflectionUtils.SetDelegate>> SetterValueFactory(Type type)
{
IDictionary<string, KeyValuePair<Type, ReflectionUtils.SetDelegate>> result = new Dictionary<string, KeyValuePair<Type, ReflectionUtils.SetDelegate>>();
foreach (PropertyInfo propertyInfo in ReflectionUtils.GetProperties(type))
{
if (propertyInfo.CanWrite)
{
MethodInfo setMethod = ReflectionUtils.GetSetterMethodInfo(propertyInfo);
if (setMethod.IsStatic || !setMethod.IsPublic)
{
continue;
}
result[MapClrMemberNameToJsonFieldName(propertyInfo.Name)] = new KeyValuePair<Type, ReflectionUtils.SetDelegate>(propertyInfo.PropertyType, ReflectionUtils.GetSetMethod(propertyInfo));
}
}
foreach (FieldInfo fieldInfo in ReflectionUtils.GetFields(type))
{
if (fieldInfo.IsInitOnly || fieldInfo.IsStatic || !fieldInfo.IsPublic)
{
continue;
}
result[MapClrMemberNameToJsonFieldName(fieldInfo.Name)] = new KeyValuePair<Type, ReflectionUtils.SetDelegate>(fieldInfo.FieldType, ReflectionUtils.GetSetMethod(fieldInfo));
}
return result;
}
public virtual bool TrySerializeNonPrimitiveObject(object input, out object output)
{
return TrySerializeKnownTypes(input, out output) || TrySerializeUnknownTypes(input, out output);
}
[SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
public virtual object DeserializeObject(object value, Type type)
{
if (type == null)
{
throw new ArgumentNullException("type");
}
string str = value as string;
if (type == typeof(Guid) && string.IsNullOrEmpty(str))
{
return default(Guid);
}
if (value == null)
{
return null;
}
object obj = null;
if (str != null)
{
if (str.Length != 0) // We know it can't be null now.
{
if (type == typeof(DateTime) || ReflectionUtils.IsNullableType(type) && Nullable.GetUnderlyingType(type) == typeof(DateTime))
{
return DateTime.ParseExact(str, PocoJsonSerializerStrategy.Iso8601Format, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal);
}
if (type == typeof(DateTimeOffset) || ReflectionUtils.IsNullableType(type) && Nullable.GetUnderlyingType(type) == typeof(DateTimeOffset))
{
return DateTimeOffset.ParseExact(str, PocoJsonSerializerStrategy.Iso8601Format, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal);
}
if (type == typeof(Guid) || ReflectionUtils.IsNullableType(type) && Nullable.GetUnderlyingType(type) == typeof(Guid))
{
return new Guid(str);
}
if (type == typeof(Uri))
{
bool isValid = Uri.IsWellFormedUriString(str, UriKind.RelativeOrAbsolute);
Uri result;
if (isValid && Uri.TryCreate(str, UriKind.RelativeOrAbsolute, out result))
{
return result;
}
return null;
}
if (type == typeof(string))
{
return str;
}
if (type == typeof(TimeSpan) || ReflectionUtils.IsNullableType(type) && Nullable.GetUnderlyingType(type) == typeof(TimeSpan))
{
return TimeSpan.Parse(str);
}
return Convert.ChangeType(str, type, CultureInfo.InvariantCulture);
}
else
{
if (type == typeof(Guid))
{
obj = default(Guid);
}
else if (ReflectionUtils.IsNullableType(type) && Nullable.GetUnderlyingType(type) == typeof(Guid))
{
obj = null;
}
else
{
obj = str;
}
}
// Empty string case
if (!ReflectionUtils.IsNullableType(type) && Nullable.GetUnderlyingType(type) == typeof(Guid))
{
return str;
}
}
if (type.IsEnum)
{
return Enum.Parse(type, value.ToString());
}
else if (value is bool)
{
return value;
}
bool valueIsLong = value is long;
bool valueIsDouble = value is double;
if (valueIsLong && type == typeof(long) || valueIsDouble && type == typeof(double))
{
return value;
}
if (valueIsDouble && type != typeof(double) || valueIsLong && type != typeof(long))
{
obj = type == typeof(int) || type == typeof(long) || type == typeof(double) || type == typeof(float) || type == typeof(bool) || type == typeof(decimal) || type == typeof(byte) || type == typeof(short) ? Convert.ChangeType(value, type, CultureInfo.InvariantCulture) : value;
}
else
{
IDictionary<string, object> objects = value as IDictionary<string, object>;
if (objects != null)
{
IDictionary<string, object> jsonObject = objects;
if (ReflectionUtils.IsTypeDictionary(type))
{
// if dictionary then
Type[] types = ReflectionUtils.GetGenericTypeArguments(type);
Type keyType = types[0];
Type valueType = types[1];
Type genericType = typeof(Dictionary<,>).MakeGenericType(keyType, valueType);
IDictionary dict = (IDictionary) ConstructorCache[genericType]();
foreach (KeyValuePair<string, object> kvp in jsonObject)
{
dict.Add(kvp.Key, this.DeserializeObject(kvp.Value, valueType));
}
obj = dict;
}
else
{
if (type == typeof(object))
{
obj = value;
}
else
{
obj = Activator.CreateInstance(type);
foreach (KeyValuePair<string, KeyValuePair<Type, ReflectionUtils.SetDelegate>> setter in SetCache[type])
{
object jsonValue;
if (jsonObject.TryGetValue(setter.Key, out jsonValue))
{
jsonValue = DeserializeObject(jsonValue, setter.Value.Key);
setter.Value.Value(obj, jsonValue);
}
else
{
string camelKey = setter.Key;
camelKey = char.ToLower(camelKey[0]) + camelKey.Substring(1);
if (jsonObject.TryGetValue(camelKey, out jsonValue))
{
jsonValue = DeserializeObject(jsonValue, setter.Value.Key);
setter.Value.Value(obj, jsonValue);
}
}
}
}
}
}
else
{
IList<object> valueAsList = value as IList<object>;
if (valueAsList != null)
{
IList<object> jsonObject = valueAsList;
IList list = null;
if (type.IsArray)
{
list = (IList) ConstructorCache[type](jsonObject.Count);
int i = 0;
foreach (object o in jsonObject)
{
list[i++] = this.DeserializeObject(o, type.GetElementType());
}
}
else if (ReflectionUtils.IsTypeGenericeCollectionInterface(type) || ReflectionUtils.IsAssignableFrom(typeof(IList), type))
{
Type innerType = ReflectionUtils.GetGenericListElementType(type);
list = (IList) (ConstructorCache[type] ?? ConstructorCache[typeof(List<>).MakeGenericType(innerType)])();
foreach (object o in jsonObject)
{
list.Add(this.DeserializeObject(o, innerType));
}
}
obj = list;
}
}
return obj;
}
if (ReflectionUtils.IsNullableType(type))
{
return ReflectionUtils.ToNullableType(obj, type);
}
return obj;
}
protected virtual object SerializeEnum(Enum p)
{
return Convert.ToDouble(p, CultureInfo.InvariantCulture);
}
[SuppressMessage("Microsoft.Design", "CA1007:UseGenericsWhereAppropriate", Justification = "Need to support .NET 2")]
protected virtual bool TrySerializeKnownTypes(object input, out object output)
{
bool returnValue = true;
if (input is DateTime)
{
output = ((DateTime) input).ToUniversalTime()
.ToString(PocoJsonSerializerStrategy.Iso8601Format[0], CultureInfo.InvariantCulture);
}
else if (input is DateTimeOffset)
{
output = ((DateTimeOffset) input).ToUniversalTime()
.ToString(PocoJsonSerializerStrategy.Iso8601Format[0], CultureInfo.InvariantCulture);
}
else if (input is TimeSpan)
{
output = ((TimeSpan) input).ToString();
}
else if (input is Guid)
{
output = ((Guid) input).ToString("D");
}
else if (input is Uri)
{
output = input.ToString();
}
else
{
Enum inputEnum = input as Enum;
if (inputEnum != null)
{
output = this.SerializeEnum(inputEnum);
}
else
{
returnValue = false;
output = null;
}
}
return returnValue;
}
[SuppressMessage("Microsoft.Design", "CA1007:UseGenericsWhereAppropriate", Justification = "Need to support .NET 2")]
protected virtual bool TrySerializeUnknownTypes(object input, out object output)
{
if (input == null)
{
throw new ArgumentNullException("input");
}
output = null;
Type type = input.GetType();
if (type.FullName == null)
{
return false;
}
IDictionary<string, object> obj = new JsonObject();
IDictionary<string, ReflectionUtils.GetDelegate> getters = GetCache[type];
foreach (KeyValuePair<string, ReflectionUtils.GetDelegate> getter in getters)
{
if (getter.Value != null)
{
obj.Add(this.MapClrMemberNameToJsonFieldName(getter.Key), getter.Value(input));
}
}
output = obj;
return true;
}
}
#if SIMPLE_JSON_DATACONTRACT
[GeneratedCode("simple-json", "1.0.0")]
#if SIMPLE_JSON_INTERNAL
internal
#else
public
#endif
class DataContractJsonSerializerStrategy : PocoJsonSerializerStrategy
{
public DataContractJsonSerializerStrategy()
{
GetCache = new ReflectionUtils.ThreadSafeDictionary<Type, IDictionary<string, ReflectionUtils.GetDelegate>>(GetterValueFactory);
SetCache = new ReflectionUtils.ThreadSafeDictionary<Type, IDictionary<string, KeyValuePair<Type, ReflectionUtils.SetDelegate>>>(SetterValueFactory);
}
internal override IDictionary<string, ReflectionUtils.GetDelegate> GetterValueFactory(Type type)
{
bool hasDataContract = ReflectionUtils.GetAttribute(type, typeof(DataContractAttribute)) != null;
if (!hasDataContract)
return base.GetterValueFactory(type);
string jsonKey;
IDictionary<string, ReflectionUtils.GetDelegate> result = new Dictionary<string, ReflectionUtils.GetDelegate>();
foreach (PropertyInfo propertyInfo in ReflectionUtils.GetProperties(type))
{
if (propertyInfo.CanRead)
{
MethodInfo getMethod = ReflectionUtils.GetGetterMethodInfo(propertyInfo);
if (!getMethod.IsStatic && CanAdd(propertyInfo, out jsonKey))
result[jsonKey] = ReflectionUtils.GetGetMethod(propertyInfo);
}
}
foreach (FieldInfo fieldInfo in ReflectionUtils.GetFields(type))
{
if (!fieldInfo.IsStatic && CanAdd(fieldInfo, out jsonKey))
result[jsonKey] = ReflectionUtils.GetGetMethod(fieldInfo);
}
return result;
}
internal override IDictionary<string, KeyValuePair<Type, ReflectionUtils.SetDelegate>> SetterValueFactory(Type type)
{
bool hasDataContract = ReflectionUtils.GetAttribute(type, typeof(DataContractAttribute)) != null;
if (!hasDataContract)
return base.SetterValueFactory(type);
string jsonKey;
IDictionary<string, KeyValuePair<Type, ReflectionUtils.SetDelegate>> result = new Dictionary<string, KeyValuePair<Type, ReflectionUtils.SetDelegate>>();
foreach (PropertyInfo propertyInfo in ReflectionUtils.GetProperties(type))
{
if (propertyInfo.CanWrite)
{
MethodInfo setMethod = ReflectionUtils.GetSetterMethodInfo(propertyInfo);
if (!setMethod.IsStatic && CanAdd(propertyInfo, out jsonKey))
result[jsonKey] = new KeyValuePair<Type, ReflectionUtils.SetDelegate>(propertyInfo.PropertyType, ReflectionUtils.GetSetMethod(propertyInfo));
}
}
foreach (FieldInfo fieldInfo in ReflectionUtils.GetFields(type))
{
if (!fieldInfo.IsInitOnly && !fieldInfo.IsStatic && CanAdd(fieldInfo, out jsonKey))
result[jsonKey] = new KeyValuePair<Type, ReflectionUtils.SetDelegate>(fieldInfo.FieldType, ReflectionUtils.GetSetMethod(fieldInfo));
}
// todo implement sorting for DATACONTRACT.
return result;
}
private static bool CanAdd(MemberInfo info, out string jsonKey)
{
jsonKey = null;
if (ReflectionUtils.GetAttribute(info, typeof(IgnoreDataMemberAttribute)) != null)
return false;
DataMemberAttribute dataMemberAttribute = (DataMemberAttribute)ReflectionUtils.GetAttribute(info, typeof(DataMemberAttribute));
if (dataMemberAttribute == null)
return false;
jsonKey = string.IsNullOrEmpty(dataMemberAttribute.Name) ? info.Name : dataMemberAttribute.Name;
return true;
}
}
#endif
namespace Reflection
{
// This class is meant to be copied into other libraries. So we want to exclude it from Code Analysis rules
// that might be in place in the target project.
[GeneratedCode("reflection-utils", "1.0.0")]
#if SIMPLE_JSON_REFLECTION_UTILS_PUBLIC
public
#else
internal
#endif
class ReflectionUtils
{
private static readonly object[] EmptyObjects = new object[] { };
public delegate object GetDelegate(object source);
public delegate void SetDelegate(object source, object value);
public delegate object ConstructorDelegate(params object[] args);
public delegate TValue ThreadSafeDictionaryValueFactory<TKey, TValue>(TKey key);
#if SIMPLE_JSON_TYPEINFO
public static TypeInfo GetTypeInfo(Type type)
{
return type.GetTypeInfo();
}
#else
public static Type GetTypeInfo(Type type)
{
return type;
}
#endif
public static Attribute GetAttribute(MemberInfo info, Type type)
{
#if SIMPLE_JSON_TYPEINFO
if (info == null || type == null || !info.IsDefined(type))
return null;
return info.GetCustomAttribute(type);
#else
if (info == null || type == null || !Attribute.IsDefined(info, type))
{
return null;
}
return Attribute.GetCustomAttribute(info, type);
#endif
}
public static Type GetGenericListElementType(Type type)
{
IEnumerable<Type> interfaces;
#if SIMPLE_JSON_TYPEINFO
interfaces = type.GetTypeInfo().ImplementedInterfaces;
#else
interfaces = type.GetInterfaces();
#endif
foreach (Type implementedInterface in interfaces)
{
if (ReflectionUtils.IsTypeGeneric(implementedInterface) && implementedInterface.GetGenericTypeDefinition() == typeof(IList<>))
{
return ReflectionUtils.GetGenericTypeArguments(implementedInterface)[0];
}
}
return ReflectionUtils.GetGenericTypeArguments(type)[0];
}
public static Attribute GetAttribute(Type objectType, Type attributeType)
{
#if SIMPLE_JSON_TYPEINFO
if (objectType == null || attributeType == null || !objectType.GetTypeInfo().IsDefined(attributeType))
return null;
return objectType.GetTypeInfo().GetCustomAttribute(attributeType);
#else
if (objectType == null || attributeType == null || !Attribute.IsDefined(objectType, attributeType))
{
return null;
}
return Attribute.GetCustomAttribute(objectType, attributeType);
#endif
}
public static Type[] GetGenericTypeArguments(Type type)
{
#if SIMPLE_JSON_TYPEINFO
return type.GetTypeInfo().GenericTypeArguments;
#else
return type.GetGenericArguments();
#endif
}
public static bool IsTypeGeneric(Type type)
{
return ReflectionUtils.GetTypeInfo(type)
.IsGenericType;
}
public static bool IsTypeGenericeCollectionInterface(Type type)
{
if (!ReflectionUtils.IsTypeGeneric(type))
{
return false;
}
Type genericDefinition = type.GetGenericTypeDefinition();
return genericDefinition == typeof(IList<>) || genericDefinition == typeof(ICollection<>) || genericDefinition == typeof(IEnumerable<>);
}
public static bool IsAssignableFrom(Type type1, Type type2)
{
return ReflectionUtils.GetTypeInfo(type1)
.IsAssignableFrom(ReflectionUtils.GetTypeInfo(type2));
}
public static bool IsTypeDictionary(Type type)
{
#if SIMPLE_JSON_TYPEINFO
if (typeof(IDictionary<,>).GetTypeInfo().IsAssignableFrom(type.GetTypeInfo()))
return true;
#else
if (typeof(System.Collections.IDictionary).IsAssignableFrom(type))
{
return true;
}
#endif
if (!ReflectionUtils.GetTypeInfo(type)
.IsGenericType)
{
return false;
}
Type genericDefinition = type.GetGenericTypeDefinition();
return genericDefinition == typeof(IDictionary<,>);
}
public static bool IsNullableType(Type type)
{
return ReflectionUtils.GetTypeInfo(type)
.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>);
}
public static object ToNullableType(object obj, Type nullableType)
{
return obj == null ? null : Convert.ChangeType(obj, Nullable.GetUnderlyingType(nullableType), CultureInfo.InvariantCulture);
}
public static bool IsValueType(Type type)
{
return ReflectionUtils.GetTypeInfo(type)
.IsValueType;
}
public static IEnumerable<ConstructorInfo> GetConstructors(Type type)
{
#if SIMPLE_JSON_TYPEINFO
return type.GetTypeInfo().DeclaredConstructors;
#else
return type.GetConstructors();
#endif
}
public static ConstructorInfo GetConstructorInfo(Type type, params Type[] argsType)
{
IEnumerable<ConstructorInfo> constructorInfos = ReflectionUtils.GetConstructors(type);
int i;
bool matches;
foreach (ConstructorInfo constructorInfo in constructorInfos)
{
ParameterInfo[] parameters = constructorInfo.GetParameters();
if (argsType.Length != parameters.Length)
{
continue;
}
i = 0;
matches = true;
foreach (ParameterInfo parameterInfo in constructorInfo.GetParameters())
{
if (parameterInfo.ParameterType != argsType[i])
{
matches = false;
break;
}
}
if (matches)
{
return constructorInfo;
}
}
return null;
}
public static IEnumerable<PropertyInfo> GetProperties(Type type)
{
#if SIMPLE_JSON_TYPEINFO
return type.GetRuntimeProperties();
#else
return type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
#endif
}
public static IEnumerable<FieldInfo> GetFields(Type type)
{
#if SIMPLE_JSON_TYPEINFO
return type.GetRuntimeFields();
#else
return type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
#endif
}
public static MethodInfo GetGetterMethodInfo(PropertyInfo propertyInfo)
{
#if SIMPLE_JSON_TYPEINFO
return propertyInfo.GetMethod;
#else
return propertyInfo.GetGetMethod(true);
#endif
}
public static MethodInfo GetSetterMethodInfo(PropertyInfo propertyInfo)
{
#if SIMPLE_JSON_TYPEINFO
return propertyInfo.SetMethod;
#else
return propertyInfo.GetSetMethod(true);
#endif
}
public static ConstructorDelegate GetContructor(ConstructorInfo constructorInfo)
{
#if SIMPLE_JSON_NO_LINQ_EXPRESSION
return ReflectionUtils.GetConstructorByReflection(constructorInfo);
#else
return ReflectionUtils.GetConstructorByExpression(constructorInfo);
#endif
}
public static ConstructorDelegate GetContructor(Type type, params Type[] argsType)
{
#if SIMPLE_JSON_NO_LINQ_EXPRESSION
return ReflectionUtils.GetConstructorByReflection(type, argsType);
#else
return ReflectionUtils.GetConstructorByExpression(type, argsType);
#endif
}
public static ConstructorDelegate GetConstructorByReflection(ConstructorInfo constructorInfo)
{
return delegate(object[] args) { return constructorInfo.Invoke(args); };
}
public static ConstructorDelegate GetConstructorByReflection(Type type, params Type[] argsType)
{
ConstructorInfo constructorInfo = ReflectionUtils.GetConstructorInfo(type, argsType);
return constructorInfo == null ? null : ReflectionUtils.GetConstructorByReflection(constructorInfo);
}
#if !SIMPLE_JSON_NO_LINQ_EXPRESSION
public static ConstructorDelegate GetConstructorByExpression(ConstructorInfo constructorInfo)
{
ParameterInfo[] paramsInfo = constructorInfo.GetParameters();
ParameterExpression param = Expression.Parameter(typeof(object[]), "args");
Expression[] argsExp = new Expression[paramsInfo.Length];
for (int i = 0; i < paramsInfo.Length; i++)
{
Expression index = Expression.Constant(i);
Type paramType = paramsInfo[i]
.ParameterType;
Expression paramAccessorExp = Expression.ArrayIndex(param, index);
Expression paramCastExp = Expression.Convert(paramAccessorExp, paramType);
argsExp[i] = paramCastExp;
}
NewExpression newExp = Expression.New(constructorInfo, argsExp);
Expression<Func<object[], object>> lambda = Expression.Lambda<Func<object[], object>>(newExp, param);
Func<object[], object> compiledLambda = lambda.Compile();
return delegate(object[] args) { return compiledLambda(args); };
}
public static ConstructorDelegate GetConstructorByExpression(Type type, params Type[] argsType)
{
ConstructorInfo constructorInfo = ReflectionUtils.GetConstructorInfo(type, argsType);
return constructorInfo == null ? null : ReflectionUtils.GetConstructorByExpression(constructorInfo);
}
#endif
public static GetDelegate GetGetMethod(PropertyInfo propertyInfo)
{
#if SIMPLE_JSON_NO_LINQ_EXPRESSION
return ReflectionUtils.GetGetMethodByReflection(propertyInfo);
#else
return ReflectionUtils.GetGetMethodByExpression(propertyInfo);
#endif
}
public static GetDelegate GetGetMethod(FieldInfo fieldInfo)
{
#if SIMPLE_JSON_NO_LINQ_EXPRESSION
return ReflectionUtils.GetGetMethodByReflection(fieldInfo);
#else
return ReflectionUtils.GetGetMethodByExpression(fieldInfo);
#endif
}
public static GetDelegate GetGetMethodByReflection(PropertyInfo propertyInfo)
{
MethodInfo methodInfo = ReflectionUtils.GetGetterMethodInfo(propertyInfo);
return delegate(object source) { return methodInfo.Invoke(source, ReflectionUtils.EmptyObjects); };
}
public static GetDelegate GetGetMethodByReflection(FieldInfo fieldInfo)
{
return delegate(object source) { return fieldInfo.GetValue(source); };
}
#if !SIMPLE_JSON_NO_LINQ_EXPRESSION
public static GetDelegate GetGetMethodByExpression(PropertyInfo propertyInfo)
{
MethodInfo getMethodInfo = ReflectionUtils.GetGetterMethodInfo(propertyInfo);
ParameterExpression instance = Expression.Parameter(typeof(object), "instance");
UnaryExpression instanceCast = !ReflectionUtils.IsValueType(propertyInfo.DeclaringType) ? Expression.TypeAs(instance, propertyInfo.DeclaringType) : Expression.Convert(instance, propertyInfo.DeclaringType);
Func<object, object> compiled = Expression.Lambda<Func<object, object>>(Expression.TypeAs(Expression.Call(instanceCast, getMethodInfo), typeof(object)), instance)
.Compile();
return delegate(object source) { return compiled(source); };
}
public static GetDelegate GetGetMethodByExpression(FieldInfo fieldInfo)
{
ParameterExpression instance = Expression.Parameter(typeof(object), "instance");
MemberExpression member = Expression.Field(Expression.Convert(instance, fieldInfo.DeclaringType), fieldInfo);
GetDelegate compiled = Expression.Lambda<GetDelegate>(Expression.Convert(member, typeof(object)), instance)
.Compile();
return delegate(object source) { return compiled(source); };
}
#endif
public static SetDelegate GetSetMethod(PropertyInfo propertyInfo)
{
#if SIMPLE_JSON_NO_LINQ_EXPRESSION
return ReflectionUtils.GetSetMethodByReflection(propertyInfo);
#else
return ReflectionUtils.GetSetMethodByExpression(propertyInfo);
#endif
}
public static SetDelegate GetSetMethod(FieldInfo fieldInfo)
{
#if SIMPLE_JSON_NO_LINQ_EXPRESSION
return ReflectionUtils.GetSetMethodByReflection(fieldInfo);
#else
return ReflectionUtils.GetSetMethodByExpression(fieldInfo);
#endif
}
public static SetDelegate GetSetMethodByReflection(PropertyInfo propertyInfo)
{
MethodInfo methodInfo = ReflectionUtils.GetSetterMethodInfo(propertyInfo);
return delegate(object source, object value) { methodInfo.Invoke(source, new object[] {value}); };
}
public static SetDelegate GetSetMethodByReflection(FieldInfo fieldInfo)
{
return delegate(object source, object value) { fieldInfo.SetValue(source, value); };
}
#if !SIMPLE_JSON_NO_LINQ_EXPRESSION
public static SetDelegate GetSetMethodByExpression(PropertyInfo propertyInfo)
{
MethodInfo setMethodInfo = ReflectionUtils.GetSetterMethodInfo(propertyInfo);
ParameterExpression instance = Expression.Parameter(typeof(object), "instance");
ParameterExpression value = Expression.Parameter(typeof(object), "value");
UnaryExpression instanceCast = !ReflectionUtils.IsValueType(propertyInfo.DeclaringType) ? Expression.TypeAs(instance, propertyInfo.DeclaringType) : Expression.Convert(instance, propertyInfo.DeclaringType);
UnaryExpression valueCast = !ReflectionUtils.IsValueType(propertyInfo.PropertyType) ? Expression.TypeAs(value, propertyInfo.PropertyType) : Expression.Convert(value, propertyInfo.PropertyType);
Action<object, object> compiled = Expression.Lambda<Action<object, object>>(Expression.Call(instanceCast, setMethodInfo, valueCast), new ParameterExpression[] {instance, value})
.Compile();
return delegate(object source, object val) { compiled(source, val); };
}
public static SetDelegate GetSetMethodByExpression(FieldInfo fieldInfo)
{
ParameterExpression instance = Expression.Parameter(typeof(object), "instance");
ParameterExpression value = Expression.Parameter(typeof(object), "value");
Action<object, object> compiled = Expression.Lambda<Action<object, object>>(ReflectionUtils.Assign(Expression.Field(Expression.Convert(instance, fieldInfo.DeclaringType), fieldInfo), Expression.Convert(value, fieldInfo.FieldType)), instance, value)
.Compile();
return delegate(object source, object val) { compiled(source, val); };
}
public static BinaryExpression Assign(Expression left, Expression right)
{
#if SIMPLE_JSON_TYPEINFO
return Expression.Assign(left, right);
#else
MethodInfo assign = typeof(Assigner<>).MakeGenericType(left.Type)
.GetMethod("Assign");
BinaryExpression assignExpr = Expression.Add(left, right, assign);
return assignExpr;
#endif
}
private static class Assigner<T>
{
#region Static Methods
public static T Assign(ref T left, T right)
{
return left = right;
}
#endregion
}
#endif
public sealed class ThreadSafeDictionary<TKey, TValue> : IDictionary<TKey, TValue>
{
#region Constructors
public ThreadSafeDictionary(ThreadSafeDictionaryValueFactory<TKey, TValue> valueFactory)
{
_valueFactory = valueFactory;
}
#endregion
#region Fields
private Dictionary<TKey, TValue> _dictionary;
private readonly object _lock = new object();
private readonly ThreadSafeDictionaryValueFactory<TKey, TValue> _valueFactory;
#endregion
#region Properties
public int Count
{
get { return _dictionary.Count; }
}
public bool IsReadOnly
{
get { throw new NotImplementedException(); }
}
public TValue this[TKey key]
{
get { return Get(key); }
set { throw new NotImplementedException(); }
}
public ICollection<TKey> Keys
{
get { return _dictionary.Keys; }
}
public ICollection<TValue> Values
{
get { return _dictionary.Values; }
}
#endregion
#region Methods
public void Add(TKey key, TValue value)
{
throw new NotImplementedException();
}
public void Add(KeyValuePair<TKey, TValue> item)
{
throw new NotImplementedException();
}
private TValue AddValue(TKey key)
{
TValue value = _valueFactory(key);
lock (_lock)
{
if (_dictionary == null)
{
_dictionary = new Dictionary<TKey, TValue>();
_dictionary[key] = value;
}
else
{
TValue val;
if (_dictionary.TryGetValue(key, out val))
{
return val;
}
Dictionary<TKey, TValue> dict = new Dictionary<TKey, TValue>(_dictionary);
dict[key] = value;
_dictionary = dict;
}
}
return value;
}
public void Clear()
{
throw new NotImplementedException();
}
public bool Contains(KeyValuePair<TKey, TValue> item)
{
throw new NotImplementedException();
}
public bool ContainsKey(TKey key)
{
return _dictionary.ContainsKey(key);
}
public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
{
throw new NotImplementedException();
}
private TValue Get(TKey key)
{
if (_dictionary == null)
{
return this.AddValue(key);
}
TValue value;
if (!_dictionary.TryGetValue(key, out value))
{
return this.AddValue(key);
}
return value;
}
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
{
return _dictionary.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return _dictionary.GetEnumerator();
}
public bool Remove(TKey key)
{
throw new NotImplementedException();
}
public bool Remove(KeyValuePair<TKey, TValue> item)
{
throw new NotImplementedException();
}
public bool TryGetValue(TKey key, out TValue value)
{
value = this[key];
return true;
}
#endregion
}
}
}
}
// ReSharper restore LoopCanBeConvertedToQuery
// ReSharper restore RedundantExplicitArrayCreation
// ReSharper restore SuggestUseVarKeywordEvident