1
0
mirror of https://github.com/Sonarr/Sonarr.git synced 2024-10-30 07:22:35 +01:00

Updated to exceptron api v1a

This commit is contained in:
kay.one 2012-04-29 18:24:24 -07:00
parent bb9e4c88ce
commit 16eecb3b4f
46 changed files with 52399 additions and 32 deletions

View File

@ -36,13 +36,11 @@
<Reference Include="Exceptioneer.WindowsFormsClient">
<HintPath>..\Libraries\Exceptioneer.WindowsFormsClient.dll</HintPath>
</Reference>
<Reference Include="Exceptrack.Driver, Version=0.1.0.96, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Exceptrack.Driver.0.1.0.3\lib\net20\Exceptrack.Driver.dll</HintPath>
<Reference Include="Exceptron.Driver">
<HintPath>..\packages\Exceptron.Driver.0.1.0.3\lib\net20\Exceptron.Driver.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Newtonsoft.Json.4.5.3\lib\net40\Newtonsoft.Json.dll</HintPath>
<HintPath>..\packages\Newtonsoft.Json.4.5.4\lib\net40\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="Ninject">
<HintPath>..\packages\Ninject.2.2.1.4\lib\net40-Full\Ninject.dll</HintPath>

View File

@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Exceptrack.Driver;
using Exceptron.Driver;
using NLog;
using NzbDrone.Common.Contract;
@ -13,10 +13,9 @@ namespace NzbDrone.Common
private const string SERVICE_URL = "http://services.nzbdrone.com/reporting";
private const string PARSE_URL = SERVICE_URL + "/ParseError";
private const string EXCEPTION_URL = SERVICE_URL + "/ReportException";
public static RestProvider RestProvider { get; set; }
public static ExceptionClient ExceptrackDriver { get; set; }
public static ExceptionClient ExceptronDriver { get; set; }
private static readonly HashSet<string> parserErrorCache = new HashSet<string>();
@ -70,7 +69,7 @@ namespace NzbDrone.Common
exceptionData.Message = logEvent.FormattedMessage;
exceptionData.UserId = EnvironmentProvider.UGuid.ToString().Replace("-", string.Empty);
return ExceptrackDriver.SubmitException(exceptionData);
return ExceptronDriver.SubmitException(exceptionData);
}
catch (Exception e)
{
@ -87,14 +86,15 @@ namespace NzbDrone.Common
}
public static void SetupExceptrackDriver()
public static void SetupExceptronDriver()
{
ExceptrackDriver = new ExceptionClient(
"CB230C312E5C4FF38B4FB9644B05E60D",
new EnvironmentProvider().Version.ToString(),
new Uri("http://api.exceptrack.com/v1/"));
ExceptronDriver = new ExceptionClient(
"CB230C312E5C4FF38B4FB9644B05E60E",
new EnvironmentProvider().Version.ToString(),
new Uri("http://api.Exceptron.com/v1aa/"));
ExceptrackDriver.ThrowsExceptions = !EnvironmentProvider.IsProduction;
ExceptronDriver.ThrowsExceptions = !EnvironmentProvider.IsProduction;
ExceptronDriver.Enviroment = EnvironmentProvider.IsProduction ? "Prod" : "Dev";
}
private static void VerifyDependencies()
@ -112,16 +112,16 @@ namespace NzbDrone.Common
}
}
if (ExceptrackDriver == null)
if (ExceptronDriver == null)
{
if (EnvironmentProvider.IsProduction)
{
logger.Warn("Exceptrack Driver wasn't provided. creating new one!");
SetupExceptrackDriver();
logger.Warn("Exceptron Driver wasn't provided. creating new one!");
SetupExceptronDriver();
}
else
{
throw new InvalidOperationException("Exceptrack Driver wasn't configured correctly.");
throw new InvalidOperationException("Exceptron Driver wasn't configured correctly.");
}
}
}

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Exceptrack.Driver" version="0.1.0.3" />
<package id="Newtonsoft.Json" version="4.5.3" />
<package id="Exceptron.Driver" version="0.1.0.3" />
<package id="Newtonsoft.Json" version="4.5.4" />
<package id="NLog" version="2.0.0.2000" />
</packages>

View File

@ -63,6 +63,11 @@ namespace NzbDrone.Core.Test.Framework
}
}
protected static void ThrowException()
{
throw new ApplicationException("This is a message for test exception");
}
[TearDown]
public void CoreTestTearDown()
{

View File

@ -58,16 +58,27 @@ namespace NzbDrone.Core.Test.Integeration
[Test]
public void should_be_able_to_submit_exceptions()
{
ReportingService.SetupExceptrackDriver();
ReportingService.SetupExceptronDriver();
var log = new LogEventInfo();
log.LoggerName = "LoggerName.LoggerName.LoggerName.LoggerName";
log.Exception = new ArgumentOutOfRangeException();
log.Message = "New message string. New message string. New message string. New message string. New message string. New message string.";
try
{
ThrowException();
}
catch (Exception e)
{
var log = new LogEventInfo
{
LoggerName = "LoggerName.LoggerName.LoggerName.LoggerName",
Exception = e,
Message = "New message string. New message string.",
};
var hash = ReportingService.ReportException(log);
hash.Should().HaveLength(8);
}
var hash = ReportingService.ReportException(log);
hash.Should().HaveLength(8);
}

View File

@ -68,7 +68,7 @@ namespace NzbDrone.Core
{
EnvironmentProvider.UGuid = Kernel.Get<ConfigProvider>().UGuid;
ReportingService.RestProvider = Kernel.Get<RestProvider>();
ReportingService.SetupExceptrackDriver();
ReportingService.SetupExceptronDriver();
var appId = AnalyticsProvider.DESKMETRICS_TEST_ID;

View File

@ -49,7 +49,7 @@ namespace NzbDrone.Test.Common
MockedRestProvider = new Mock<RestProvider>();
ReportingService.RestProvider = MockedRestProvider.Object;
ReportingService.SetupExceptrackDriver();
ReportingService.SetupExceptronDriver();
if (Directory.Exists(TempFolder))

View File

@ -62,7 +62,7 @@ namespace NzbDrone.Update
private static void InitLoggers()
{
ReportingService.RestProvider = _kernel.Get<RestProvider>();
ReportingService.SetupExceptrackDriver();
ReportingService.SetupExceptronDriver();
LogConfiguration.RegisterRemote();

View File

@ -46,7 +46,7 @@ namespace NzbDrone
var environmentProvider = _kernel.Get<EnvironmentProvider>();
ReportingService.RestProvider = _kernel.Get<RestProvider>();
ReportingService.SetupExceptrackDriver();
ReportingService.SetupExceptronDriver();
LogConfiguration.RegisterRollingFileLogger(environmentProvider.GetLogFileName(), LogLevel.Info);
LogConfiguration.RegisterConsoleLogger(LogLevel.Debug);

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,116 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Reflection;
using System.Text;
using Exceptron.Driver.fastJSON;
namespace Exceptron.Driver
{
public class ExceptionClient
{
private const string DriverName = "Official .NET";
private static readonly string DriverVersion = Assembly.GetExecutingAssembly().GetName().Version.ToString();
private readonly string _serverUrl;
private readonly string _appId;
private readonly string _appVersion;
public bool ThrowsExceptions { get; set; }
public string Enviroment { get; set; }
public ExceptionClient(string appId, string appVersion, Uri serverUrl)
{
_appId = appId;
_appVersion = appVersion;
_serverUrl = serverUrl.ToString();
}
private static List<Frame> GetExceptionFrames(Exception exception)
{
if (exception == null) return null;
var stackTrace = new StackTrace(exception, true);
var frames = stackTrace.GetFrames();
if (frames == null) return null;
var result = new List<Frame>();
foreach (var frame in frames)
{
result.Add(new Frame { FileName = frame.GetFileName(), LineNumber = frame.GetFileLineNumber(), Method = frame.GetMethod().Name });
}
return result;
}
public string SubmitException(ExceptionData exceptionData)
{
try
{
VerifyErrorData(exceptionData);
var report = new ExceptionReport();
report.AppId = _appId;
report.DriverName = DriverName;
report.DriverVersion = DriverVersion;
report.AppVersion = _appVersion;
report.ExceptionType = exceptionData.Exception.GetType().FullName;
report.ExceptionMessage = exceptionData.Exception.Message;
report.StackTrace = GetExceptionFrames(exceptionData.Exception);
report.Location = exceptionData.Location;
report.Uid = exceptionData.UserId;
report.Enviroment = Enviroment;
report.Message = exceptionData.Message;
var response = PutObject(report);
return response;
}
catch (Exception)
{
if (ThrowsExceptions) throw;
return null;
}
}
private void VerifyErrorData(ExceptionData exceptionData)
{
if (exceptionData == null)
throw new ArgumentNullException("exceptionData");
if (exceptionData.Exception == null)
throw new ArgumentException("ExceptionData.Exception Cannot be null.", "exceptionData");
}
private string PutObject(ExceptionReport exceptionReport)
{
string exceptionData = JSON.Instance.ToJSON(exceptionReport);
byte[] bytes = Encoding.UTF8.GetBytes(exceptionData);
var request = (HttpWebRequest)WebRequest.Create(_serverUrl);
request.Method = "PUT";
request.ContentType = "application/json";
request.ContentLength = bytes.Length;
request.Accept = "application/json";
var dataStream = request.GetRequestStream();
dataStream.Write(bytes, 0, bytes.Length);
dataStream.Close();
var responseStream = new StreamReader(request.GetResponse().GetResponseStream(), Encoding.GetEncoding(1252));
string response = responseStream.ReadToEnd();
return response;
}
}
}

View File

@ -0,0 +1,12 @@
using System;
namespace Exceptron.Driver
{
public class ExceptionData
{
public Exception Exception { get; set; }
public string Location { get; set; }
public string UserId { get; set; }
public string Message { get; set; }
}
}

View File

@ -0,0 +1,22 @@
using System.Collections.Generic;
using System.ComponentModel;
namespace Exceptron.Driver
{
[EditorBrowsable(EditorBrowsableState.Never)]
public class ExceptionReport
{
public string AppId { get; set; }
public string AppVersion { get; set; }
public string Uid { get; set; }
public string ExceptionType { get; set; }
public string ExceptionMessage { get; set; }
public List<Frame> StackTrace { get; set; }
public string Location { get; set; }
public string Enviroment { get; set; }
public string Message { get; set; }
public string DriverName { get; set; }
public string DriverVersion { get; set; }
}
}

View File

@ -0,0 +1,9 @@
namespace Exceptron.Driver
{
public class Frame
{
public int LineNumber { get; set; }
public string FileName { get; set; }
public string Method { get; set; }
}
}

View File

@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
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("Exceptron.Driver")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Exceptron.Driver")]
[assembly: AssemblyCopyright("Copyright © 2012")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("a463887e-594f-4733-b227-a79f4ffb2158")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@ -0,0 +1,21 @@
//http://fastjson.codeplex.com/
using System;
using System.Collections.Generic;
using Exceptron.Driver.fastJSON;
namespace Exceptron.Driver.fastJSON
{
internal class Getters
{
public string Name;
public JSON.GenericGetter Getter;
public Type propertyType;
}
internal class DatasetSchema
{
public List<string> Info { get; set; }
public string Name { get; set; }
}
}

View File

@ -0,0 +1,906 @@
//http://fastjson.codeplex.com/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Reflection.Emit;
using Exceptron.Driver.fastJSON;
namespace Exceptron.Driver.fastJSON
{
internal delegate string Serialize(object data);
internal delegate object Deserialize(string data);
internal class JSON
{
public readonly static JSON Instance = new JSON();
private JSON()
{
}
public bool UseOptimizedDatasetSchema = true;
public bool UseFastGuid = true;
public bool UseSerializerExtension = true;
public bool IndentOutput = false;
public bool SerializeNullValues = true;
public bool UseUTCDateTime = false;
public bool ShowReadOnlyProperties = false;
public bool UsingGlobalTypes = true;
public string ToJSON(object obj)
{
return ToJSON(obj, UseSerializerExtension, UseFastGuid, UseOptimizedDatasetSchema, SerializeNullValues);
}
public string ToJSON(object obj,
bool enableSerializerExtensions)
{
return ToJSON(obj, enableSerializerExtensions, UseFastGuid, UseOptimizedDatasetSchema, SerializeNullValues);
}
public string ToJSON(object obj,
bool enableSerializerExtensions,
bool enableFastGuid)
{
return ToJSON(obj, enableSerializerExtensions, enableFastGuid, UseOptimizedDatasetSchema, SerializeNullValues);
}
public string ToJSON(object obj,
bool enableSerializerExtensions,
bool enableFastGuid,
bool enableOptimizedDatasetSchema,
bool serializeNullValues)
{
return new JSONSerializer(enableOptimizedDatasetSchema, enableFastGuid, enableSerializerExtensions, serializeNullValues, IndentOutput).ConvertToJSON(obj);
}
public object Parse(string json)
{
return new JsonParser(json).Decode();
}
public T ToObject<T>(string json)
{
return (T)ToObject(json, typeof(T));
}
public object ToObject(string json)
{
return ToObject(json, null);
}
public object ToObject(string json, Type type)
{
Dictionary<string, object> ht = new JsonParser(json).Decode() as Dictionary<string, object>;
if (ht == null) return null;
return ParseDictionary(ht, null, type);
}
#if CUSTOMTYPE
internal SafeDictionary<Type, Serialize> _customSerializer = new SafeDictionary<Type, Serialize>();
internal SafeDictionary<Type, Deserialize> _customDeserializer = new SafeDictionary<Type, Deserialize>();
public void RegisterCustomType(Type type, Serialize serializer, Deserialize deserializer)
{
if (type != null && serializer != null && deserializer != null)
{
_customSerializer.Add(type, serializer);
_customDeserializer.Add(type, deserializer);
// reset property cache
_propertycache = new SafeDictionary<string, SafeDictionary<string, myPropInfo>>();
}
}
internal bool IsTypeRegistered(Type t)
{
Serialize s;
return _customSerializer.TryGetValue(t, out s);
}
#endif
#region [ PROPERTY GET SET CACHE ]
SafeDictionary<Type, string> _tyname = new SafeDictionary<Type, string>();
internal string GetTypeAssemblyName(Type t)
{
string val = "";
if (_tyname.TryGetValue(t, out val))
return val;
else
{
string s = t.AssemblyQualifiedName;
_tyname.Add(t, s);
return s;
}
}
SafeDictionary<string, Type> _typecache = new SafeDictionary<string, Type>();
private Type GetTypeFromCache(string typename)
{
Type val = null;
if (_typecache.TryGetValue(typename, out val))
return val;
else
{
Type t = Type.GetType(typename);
_typecache.Add(typename, t);
return t;
}
}
SafeDictionary<Type, CreateObject> _constrcache = new SafeDictionary<Type, CreateObject>();
private delegate object CreateObject();
private object FastCreateInstance(Type objtype)
{
try
{
CreateObject c = null;
if (_constrcache.TryGetValue(objtype, out c))
{
return c();
}
else
{
DynamicMethod dynMethod = new DynamicMethod("_", objtype, null);
ILGenerator ilGen = dynMethod.GetILGenerator();
ilGen.Emit(OpCodes.Newobj, objtype.GetConstructor(Type.EmptyTypes));
ilGen.Emit(OpCodes.Ret);
c = (CreateObject)dynMethod.CreateDelegate(typeof(CreateObject));
_constrcache.Add(objtype, c);
return c();
}
}
catch (Exception exc)
{
throw new Exception(string.Format("Failed to fast create instance for type '{0}' from assemebly '{1}'",
objtype.FullName, objtype.AssemblyQualifiedName), exc);
}
}
private struct myPropInfo
{
public bool filled;
public Type pt;
public Type bt;
public Type changeType;
public bool isDictionary;
public bool isValueType;
public bool isGenericType;
public bool isArray;
public bool isByteArray;
public bool isGuid;
#if !SILVERLIGHT
public bool isDataSet;
public bool isDataTable;
public bool isHashtable;
#endif
public GenericSetter setter;
public bool isEnum;
public bool isDateTime;
public Type[] GenericTypes;
public bool isInt;
public bool isLong;
public bool isString;
public bool isBool;
public bool isClass;
public GenericGetter getter;
public bool isStringDictionary;
public string Name;
#if CUSTOMTYPE
public bool isCustomType;
#endif
public bool CanWrite;
}
SafeDictionary<string, SafeDictionary<string, myPropInfo>> _propertycache = new SafeDictionary<string, SafeDictionary<string, myPropInfo>>();
private SafeDictionary<string, myPropInfo> Getproperties(Type type, string typename)
{
SafeDictionary<string, myPropInfo> sd = null;
if (_propertycache.TryGetValue(typename, out sd))
{
return sd;
}
else
{
sd = new SafeDictionary<string, myPropInfo>();
PropertyInfo[] pr = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (PropertyInfo p in pr)
{
myPropInfo d = CreateMyProp(p.PropertyType, p.Name);
d.CanWrite = p.CanWrite;
d.setter = CreateSetMethod(p);
d.getter = CreateGetMethod(p);
sd.Add(p.Name, d);
}
FieldInfo[] fi = type.GetFields(BindingFlags.Public | BindingFlags.Instance);
foreach (FieldInfo f in fi)
{
myPropInfo d = CreateMyProp(f.FieldType, f.Name);
d.setter = CreateSetField(type, f);
d.getter = CreateGetField(type, f);
sd.Add(f.Name, d);
}
_propertycache.Add(typename, sd);
return sd;
}
}
private myPropInfo CreateMyProp(Type t, string name)
{
myPropInfo d = new myPropInfo();
d.filled = true;
d.CanWrite = true;
d.pt = t;
d.Name = name;
d.isDictionary = t.Name.Contains("Dictionary");
if (d.isDictionary)
d.GenericTypes = t.GetGenericArguments();
d.isValueType = t.IsValueType;
d.isGenericType = t.IsGenericType;
d.isArray = t.IsArray;
if (d.isArray)
d.bt = t.GetElementType();
if (d.isGenericType)
d.bt = t.GetGenericArguments()[0];
d.isByteArray = t == typeof(byte[]);
d.isGuid = (t == typeof(Guid) || t == typeof(Guid?));
#if !SILVERLIGHT
d.isHashtable = t == typeof(Hashtable);
d.isDataSet = t == typeof(DataSet);
d.isDataTable = t == typeof(DataTable);
#endif
d.changeType = GetChangeType(t);
d.isEnum = t.IsEnum;
d.isDateTime = t == typeof(DateTime) || t == typeof(DateTime?);
d.isInt = t == typeof(int) || t == typeof(int?);
d.isLong = t == typeof(long) || t == typeof(long?);
d.isString = t == typeof(string);
d.isBool = t == typeof(bool) || t == typeof(bool?);
d.isClass = t.IsClass;
if (d.isDictionary && d.GenericTypes.Length>0 && d.GenericTypes[0] == typeof(string))
d.isStringDictionary = true;
#if CUSTOMTYPE
if (IsTypeRegistered(t))
d.isCustomType = true;
#endif
return d;
}
private delegate void GenericSetter(object target, object value);
private static GenericSetter CreateSetMethod(PropertyInfo propertyInfo)
{
MethodInfo setMethod = propertyInfo.GetSetMethod();
if (setMethod == null)
return null;
Type[] arguments = new Type[2];
arguments[0] = arguments[1] = typeof(object);
DynamicMethod setter = new DynamicMethod("_", typeof(void), arguments);
ILGenerator il = setter.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Castclass, propertyInfo.DeclaringType);
il.Emit(OpCodes.Ldarg_1);
if (propertyInfo.PropertyType.IsClass)
il.Emit(OpCodes.Castclass, propertyInfo.PropertyType);
else
il.Emit(OpCodes.Unbox_Any, propertyInfo.PropertyType);
il.EmitCall(OpCodes.Callvirt, setMethod, null);
il.Emit(OpCodes.Ret);
return (GenericSetter)setter.CreateDelegate(typeof(GenericSetter));
}
internal delegate object GenericGetter(object obj);
private static GenericGetter CreateGetField(Type type, FieldInfo fieldInfo)
{
DynamicMethod dynamicGet = new DynamicMethod("_", typeof(object), new Type[] { typeof(object) }, type, true);
ILGenerator il = dynamicGet.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldfld, fieldInfo);
if (fieldInfo.FieldType.IsValueType)
il.Emit(OpCodes.Box, fieldInfo.FieldType);
il.Emit(OpCodes.Ret);
return (GenericGetter)dynamicGet.CreateDelegate(typeof(GenericGetter));
}
private static GenericSetter CreateSetField(Type type, FieldInfo fieldInfo)
{
Type[] arguments = new Type[2];
arguments[0] = arguments[1] = typeof(object);
DynamicMethod dynamicSet = new DynamicMethod("_", typeof(void), arguments, type, true);
ILGenerator il = dynamicSet.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldarg_1);
if (fieldInfo.FieldType.IsValueType)
il.Emit(OpCodes.Unbox_Any, fieldInfo.FieldType);
il.Emit(OpCodes.Stfld, fieldInfo);
il.Emit(OpCodes.Ret);
return (GenericSetter)dynamicSet.CreateDelegate(typeof(GenericSetter));
}
private GenericGetter CreateGetMethod(PropertyInfo propertyInfo)
{
MethodInfo getMethod = propertyInfo.GetGetMethod();
if (getMethod == null)
return null;
Type[] arguments = new Type[1];
arguments[0] = typeof(object);
DynamicMethod getter = new DynamicMethod("_", typeof(object), arguments);
ILGenerator il = getter.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Castclass, propertyInfo.DeclaringType);
il.EmitCall(OpCodes.Callvirt, getMethod, null);
if (!propertyInfo.PropertyType.IsClass)
il.Emit(OpCodes.Box, propertyInfo.PropertyType);
il.Emit(OpCodes.Ret);
return (GenericGetter)getter.CreateDelegate(typeof(GenericGetter));
}
readonly SafeDictionary<Type, List<Getters>> _getterscache = new SafeDictionary<Type, List<Getters>>();
internal List<Getters> GetGetters(Type type)
{
List<Getters> val = null;
if (_getterscache.TryGetValue(type, out val))
return val;
PropertyInfo[] props = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
List<Getters> getters = new List<Getters>();
foreach (PropertyInfo p in props)
{
if (!p.CanWrite && ShowReadOnlyProperties == false) continue;
object[] att = p.GetCustomAttributes(typeof(System.Xml.Serialization.XmlIgnoreAttribute), false);
if (att != null && att.Length > 0)
continue;
JSON.GenericGetter g = CreateGetMethod(p);
if (g != null)
{
Getters gg = new Getters();
gg.Name = p.Name;
gg.Getter = g;
gg.propertyType = p.PropertyType;
getters.Add(gg);
}
}
FieldInfo[] fi = type.GetFields(BindingFlags.Instance | BindingFlags.Public);
foreach (var f in fi)
{
object[] att = f.GetCustomAttributes(typeof(System.Xml.Serialization.XmlIgnoreAttribute), false);
if (att != null && att.Length > 0)
continue;
JSON.GenericGetter g = CreateGetField(type, f);
if (g != null)
{
Getters gg = new Getters();
gg.Name = f.Name;
gg.Getter = g;
gg.propertyType = f.FieldType;
getters.Add(gg);
}
}
_getterscache.Add(type, getters);
return getters;
}
private object ChangeType(object value, Type conversionType)
{
if (conversionType == typeof(int))
return (int)CreateLong((string)value);
else if (conversionType == typeof(long))
return CreateLong((string)value);
else if (conversionType == typeof(string))
return (string)value;
else if (conversionType == typeof(Guid))
return CreateGuid((string)value);
else if (conversionType.IsEnum)
return CreateEnum(conversionType, (string)value);
return Convert.ChangeType(value, conversionType, CultureInfo.InvariantCulture);
}
#endregion
private object ParseDictionary(Dictionary<string, object> d, Dictionary<string, object> globaltypes, Type type)
{
object tn = "";
if (d.TryGetValue("$types", out tn))
{
UsingGlobalTypes = true;
globaltypes = new Dictionary<string, object>();
foreach (var kv in (Dictionary<string, object>)tn)
{
globaltypes.Add((string)kv.Value, kv.Key);
}
}
bool found = d.TryGetValue("$type", out tn);
#if !SILVERLIGHT
if (found == false && type == typeof(System.Object))
{
return CreateDataset(d, globaltypes);
}
#endif
if (found)
{
if (UsingGlobalTypes)
{
object tname = "";
if (globaltypes.TryGetValue((string)tn, out tname))
tn = tname;
}
type = GetTypeFromCache((string)tn);
}
if (type == null)
throw new Exception("Cannot determine type");
string typename = type.FullName;
object o = FastCreateInstance(type);
SafeDictionary<string, myPropInfo> props = Getproperties(type, typename);
foreach (string name in d.Keys)
{
if (name == "$map")
{
ProcessMap(o, props, (Dictionary<string, object>)d[name]);
continue;
}
myPropInfo pi;
if (props.TryGetValue(name, out pi) == false)
continue;
if (pi.filled == true)
{
object v = d[name];
if (v != null)
{
object oset = null;
if (pi.isInt)
oset = (int)CreateLong((string)v);
#if CUSTOMTYPE
else if (pi.isCustomType)
oset = CreateCustom((string)v, pi.pt);
#endif
else if (pi.isLong)
oset = CreateLong((string)v);
else if (pi.isString)
oset = (string)v;
else if (pi.isBool)
oset = (bool)v;
else if (pi.isGenericType && pi.isValueType == false && pi.isDictionary == false)
#if SILVERLIGHT
oset = CreateGenericList((List<object>)v, pi.pt, pi.bt, globaltypes);
#else
oset = CreateGenericList((ArrayList)v, pi.pt, pi.bt, globaltypes);
#endif
else if (pi.isByteArray)
oset = Convert.FromBase64String((string)v);
else if (pi.isArray && pi.isValueType == false)
#if SILVERLIGHT
oset = CreateArray((List<object>)v, pi.pt, pi.bt, globaltypes);
#else
oset = CreateArray((ArrayList)v, pi.pt, pi.bt, globaltypes);
#endif
else if (pi.isGuid)
oset = CreateGuid((string)v);
#if !SILVERLIGHT
else if (pi.isDataSet)
oset = CreateDataset((Dictionary<string, object>)v, globaltypes);
else if (pi.isDataTable)
oset = this.CreateDataTable((Dictionary<string, object>)v, globaltypes);
#endif
else if (pi.isStringDictionary)
oset = CreateStringKeyDictionary((Dictionary<string, object>)v, pi.pt, pi.GenericTypes, globaltypes);
#if !SILVERLIGHT
else if (pi.isDictionary || pi.isHashtable)
oset = CreateDictionary((ArrayList)v, pi.pt, pi.GenericTypes, globaltypes);
#else
else if (pi.isDictionary)
oset = CreateDictionary((List<object>)v, pi.pt, pi.GenericTypes, globaltypes);
#endif
else if (pi.isEnum)
oset = CreateEnum(pi.pt, (string)v);
else if (pi.isDateTime)
oset = CreateDateTime((string)v);
else if (pi.isClass && v is Dictionary<string, object>)
oset = ParseDictionary((Dictionary<string, object>)v, globaltypes, pi.pt);
else if (pi.isValueType)
oset = ChangeType(v, pi.changeType);
#if SILVERLIGHT
else if (v is List<object>)
oset = CreateArray((List<object>)v, pi.pt, typeof(object), globaltypes);
#else
else if (v is ArrayList)
oset = CreateArray((ArrayList)v, pi.pt, typeof(object), globaltypes);
#endif
else
oset = v;
if (pi.CanWrite)
pi.setter(o, oset);
}
}
}
return o;
}
#if CUSTOMTYPE
private object CreateCustom(string v, Type type)
{
Deserialize d;
_customDeserializer.TryGetValue(type, out d);
return d(v);
}
#endif
private void ProcessMap(object obj, SafeDictionary<string, JSON.myPropInfo> props, Dictionary<string, object> dic)
{
foreach (KeyValuePair<string, object> kv in dic)
{
myPropInfo p = props[kv.Key];
object o = p.getter(obj);
Type t = Type.GetType((string)kv.Value);
if (t == typeof(Guid))
p.setter(obj, CreateGuid((string)o));
}
}
private long CreateLong(string s)
{
long num = 0;
bool neg = false;
foreach (char cc in s)
{
if (cc == '-')
neg = true;
else if (cc == '+')
neg = false;
else
{
num *= 10;
num += (int)(cc - '0');
}
}
return neg ? -num : num;
}
private object CreateEnum(Type pt, string v)
{
// TODO : optimize create enum
#if !SILVERLIGHT
return Enum.Parse(pt, v);
#else
return Enum.Parse(pt, v, true);
#endif
}
private Guid CreateGuid(string s)
{
if (s.Length > 30)
return new Guid(s);
else
return new Guid(Convert.FromBase64String(s));
}
private DateTime CreateDateTime(string value)
{
bool utc = false;
// 0123456789012345678
// datetime format = yyyy-MM-dd HH:mm:ss
int year = (int)CreateLong(value.Substring(0, 4));
int month = (int)CreateLong(value.Substring(5, 2));
int day = (int)CreateLong(value.Substring(8, 2));
int hour = (int)CreateLong(value.Substring(11, 2));
int min = (int)CreateLong(value.Substring(14, 2));
int sec = (int)CreateLong(value.Substring(17, 2));
if (value.EndsWith("Z"))
utc = true;
if (UseUTCDateTime == false && utc == false)
return new DateTime(year, month, day, hour, min, sec);
else
return new DateTime(year, month, day, hour, min, sec, DateTimeKind.Utc).ToLocalTime();
}
#if SILVERLIGHT
private object CreateArray(List<object> data, Type pt, Type bt, Dictionary<string, object> globalTypes)
{
Array col = Array.CreateInstance(bt, data.Count);
// create an array of objects
for (int i = 0; i < data.Count; i++)// each (object ob in data)
{
object ob = data[i];
if (ob is IDictionary)
col.SetValue(ParseDictionary((Dictionary<string, object>)ob, globalTypes, bt), i);
else
col.SetValue(ChangeType(ob, bt), i);
}
return col;
}
#else
private object CreateArray(ArrayList data, Type pt, Type bt, Dictionary<string, object> globalTypes)
{
ArrayList col = new ArrayList();
// create an array of objects
foreach (object ob in data)
{
if (ob is IDictionary)
col.Add(ParseDictionary((Dictionary<string, object>)ob, globalTypes, bt));
else
col.Add(ChangeType(ob, bt));
}
return col.ToArray(bt);
}
#endif
#if SILVERLIGHT
private object CreateGenericList(List<object> data, Type pt, Type bt, Dictionary<string, object> globalTypes)
#else
private object CreateGenericList(ArrayList data, Type pt, Type bt, Dictionary<string, object> globalTypes)
#endif
{
IList col = (IList)FastCreateInstance(pt);
// create an array of objects
foreach (object ob in data)
{
if (ob is IDictionary)
col.Add(ParseDictionary((Dictionary<string, object>)ob, globalTypes, bt));
#if SILVERLIGHT
else if (ob is List<object>)
col.Add(((List<object>)ob).ToArray());
#else
else if (ob is ArrayList)
col.Add(((ArrayList)ob).ToArray());
#endif
else
col.Add(ChangeType(ob, bt));
}
return col;
}
private object CreateStringKeyDictionary(Dictionary<string, object> reader, Type pt, Type[] types, Dictionary<string,object> globalTypes)
{
var col = (IDictionary)FastCreateInstance(pt);
Type t1 = null;
Type t2 = null;
if (types != null)
{
t1 = types[0];
t2 = types[1];
}
foreach (KeyValuePair<string, object> values in reader)
{
var key = values.Key;//ChangeType(values.Key, t1);
object val = null;
if (values.Value is Dictionary<string, object>)
val = ParseDictionary((Dictionary<string, object>)values.Value, globalTypes, t2);
else
val = ChangeType(values.Value, t2);
col.Add(key, val);
}
return col;
}
#if SILVERLIGHT
private object CreateDictionary(List<object> reader, Type pt, Type[] types, Dictionary<string, object> globalTypes)
#else
private object CreateDictionary(ArrayList reader, Type pt, Type[] types, Dictionary<string, object> globalTypes)
#endif
{
IDictionary col = (IDictionary)FastCreateInstance(pt);
Type t1 = null;
Type t2 = null;
if (types != null)
{
t1 = types[0];
t2 = types[1];
}
foreach (Dictionary<string, object> values in reader)
{
object key = values["k"];
object val = values["v"];
if (key is Dictionary<string, object>)
key = ParseDictionary((Dictionary<string, object>)key, globalTypes, t1);
else
key = ChangeType(key, t1);
if (val is Dictionary<string, object>)
val = ParseDictionary((Dictionary<string, object>)val, globalTypes, t2);
else
val = ChangeType(val, t2);
col.Add(key, val);
}
return col;
}
private Type GetChangeType(Type conversionType)
{
if (conversionType.IsGenericType && conversionType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
return conversionType.GetGenericArguments()[0];
return conversionType;
}
#if !SILVERLIGHT
private DataSet CreateDataset(Dictionary<string, object> reader, Dictionary<string, object> globalTypes)
{
DataSet ds = new DataSet();
ds.EnforceConstraints = false;
ds.BeginInit();
// read dataset schema here
ReadSchema(reader, ds, globalTypes);
foreach (KeyValuePair<string, object> pair in reader)
{
if (pair.Key == "$type" || pair.Key == "$schema") continue;
ArrayList rows = (ArrayList)pair.Value;
if (rows == null) continue;
DataTable dt = ds.Tables[pair.Key];
ReadDataTable(rows, dt);
}
ds.EndInit();
return ds;
}
private void ReadSchema(Dictionary<string, object> reader, DataSet ds, Dictionary<string, object> globalTypes)
{
var schema = reader["$schema"];
if (schema is string)
{
TextReader tr = new StringReader((string)schema);
ds.ReadXmlSchema(tr);
}
else
{
DatasetSchema ms = (DatasetSchema)ParseDictionary((Dictionary<string, object>)schema, globalTypes, typeof(DatasetSchema));
ds.DataSetName = ms.Name;
for (int i = 0; i < ms.Info.Count; i += 3)
{
if (ds.Tables.Contains(ms.Info[i]) == false)
ds.Tables.Add(ms.Info[i]);
ds.Tables[ms.Info[i]].Columns.Add(ms.Info[i + 1], Type.GetType(ms.Info[i + 2]));
}
}
}
private void ReadDataTable(ArrayList rows, DataTable dt)
{
dt.BeginInit();
dt.BeginLoadData();
List<int> guidcols = new List<int>();
List<int> datecol = new List<int>();
foreach (DataColumn c in dt.Columns)
{
if (c.DataType == typeof(Guid) || c.DataType == typeof(Guid?))
guidcols.Add(c.Ordinal);
if (UseUTCDateTime && (c.DataType == typeof(DateTime) || c.DataType == typeof(DateTime?)))
datecol.Add(c.Ordinal);
}
foreach (ArrayList row in rows)
{
object[] v = new object[row.Count];
row.CopyTo(v, 0);
foreach (int i in guidcols)
{
string s = (string)v[i];
if (s != null && s.Length < 36)
v[i] = new Guid(Convert.FromBase64String(s));
}
if (UseUTCDateTime)
{
foreach (int i in datecol)
{
string s = (string)v[i];
if (s != null)
v[i] = CreateDateTime(s);
}
}
dt.Rows.Add(v);
}
dt.EndLoadData();
dt.EndInit();
}
DataTable CreateDataTable(Dictionary<string, object> reader, Dictionary<string, object> globalTypes)
{
var dt = new DataTable();
// read dataset schema here
var schema = reader["$schema"];
if (schema is string)
{
TextReader tr = new StringReader((string)schema);
dt.ReadXmlSchema(tr);
}
else
{
var ms = (DatasetSchema)this.ParseDictionary((Dictionary<string, object>)schema, globalTypes, typeof(DatasetSchema));
dt.TableName = ms.Info[0];
for (int i = 0; i < ms.Info.Count; i += 3)
{
dt.Columns.Add(ms.Info[i + 1], Type.GetType(ms.Info[i + 2]));
}
}
foreach (var pair in reader)
{
if (pair.Key == "$type" || pair.Key == "$schema")
continue;
var rows = (ArrayList)pair.Value;
if (rows == null)
continue;
if (!dt.TableName.Equals(pair.Key, StringComparison.InvariantCultureIgnoreCase))
continue;
ReadDataTable(rows, dt);
}
return dt;
}
#endif
}
}

View File

@ -0,0 +1,408 @@
//http://fastjson.codeplex.com/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
namespace Exceptron.Driver.fastJSON
{
/// <summary>
/// This class encodes and decodes JSON strings.
/// Spec. details, see http://www.json.org/
///
/// JSON uses Arrays and Objects. These correspond here to the datatypes ArrayList and Hashtable.
/// All numbers are parsed to doubles.
/// </summary>
internal class JsonParser
{
enum Token
{
None = -1, // Used to denote no Lookahead available
Curly_Open,
Curly_Close,
Squared_Open,
Squared_Close,
Colon,
Comma,
String,
Number,
True,
False,
Null
}
readonly char[] json;
readonly StringBuilder s = new StringBuilder();
Token lookAheadToken = Token.None;
int index;
internal JsonParser(string json)
{
this.json = json.ToCharArray();
}
public object Decode()
{
return ParseValue();
}
private Dictionary<string, object> ParseObject()
{
Dictionary<string, object> table = new Dictionary<string, object>();
ConsumeToken(); // {
while (true)
{
switch (LookAhead())
{
case Token.Comma:
ConsumeToken();
break;
case Token.Curly_Close:
ConsumeToken();
return table;
default:
{
// name
string name = ParseString();
// :
if (NextToken() != Token.Colon)
{
throw new Exception("Expected colon at index " + index);
}
// value
object value = ParseValue();
table[name] = value;
}
break;
}
}
}
#if SILVERLIGHT
private List<object> ParseArray()
{
List<object> array = new List<object>();
#else
private ArrayList ParseArray()
{
ArrayList array = new ArrayList();
#endif
ConsumeToken(); // [
while (true)
{
switch (LookAhead())
{
case Token.Comma:
ConsumeToken();
break;
case Token.Squared_Close:
ConsumeToken();
return array;
default:
{
array.Add(ParseValue());
}
break;
}
}
}
private object ParseValue()
{
switch (LookAhead())
{
case Token.Number:
return ParseNumber();
case Token.String:
return ParseString();
case Token.Curly_Open:
return ParseObject();
case Token.Squared_Open:
return ParseArray();
case Token.True:
ConsumeToken();
return true;
case Token.False:
ConsumeToken();
return false;
case Token.Null:
ConsumeToken();
return null;
}
throw new Exception("Unrecognized token at index" + index);
}
private string ParseString()
{
ConsumeToken(); // "
s.Length = 0;
int runIndex = -1;
while (index < json.Length)
{
var c = json[index++];
if (c == '"')
{
if (runIndex != -1)
{
if (s.Length == 0)
return new string(json, runIndex, index - runIndex - 1);
s.Append(json, runIndex, index - runIndex - 1);
}
return s.ToString();
}
if (c != '\\')
{
if (runIndex == -1)
runIndex = index - 1;
continue;
}
if (index == json.Length) break;
if (runIndex != -1)
{
s.Append(json, runIndex, index - runIndex - 1);
runIndex = -1;
}
switch (json[index++])
{
case '"':
s.Append('"');
break;
case '\\':
s.Append('\\');
break;
case '/':
s.Append('/');
break;
case 'b':
s.Append('\b');
break;
case 'f':
s.Append('\f');
break;
case 'n':
s.Append('\n');
break;
case 'r':
s.Append('\r');
break;
case 't':
s.Append('\t');
break;
case 'u':
{
int remainingLength = json.Length - index;
if (remainingLength < 4) break;
// parse the 32 bit hex into an integer codepoint
uint codePoint = ParseUnicode(json[index], json[index + 1], json[index + 2], json[index + 3]);
s.Append((char)codePoint);
// skip 4 chars
index += 4;
}
break;
}
}
throw new Exception("Unexpectedly reached end of string");
}
private uint ParseSingleChar(char c1, uint multipliyer)
{
uint p1 = 0;
if (c1 >= '0' && c1 <= '9')
p1 = (uint)(c1 - '0') * multipliyer;
else if (c1 >= 'A' && c1 <= 'F')
p1 = (uint)((c1 - 'A') + 10) * multipliyer;
else if (c1 >= 'a' && c1 <= 'f')
p1 = (uint)((c1 - 'a') + 10) * multipliyer;
return p1;
}
private uint ParseUnicode(char c1, char c2, char c3, char c4)
{
uint p1 = ParseSingleChar(c1, 0x1000);
uint p2 = ParseSingleChar(c2, 0x100);
uint p3 = ParseSingleChar(c3, 0x10);
uint p4 = ParseSingleChar(c4, 1);
return p1 + p2 + p3 + p4;
}
private string ParseNumber()
{
ConsumeToken();
// Need to start back one place because the first digit is also a token and would have been consumed
var startIndex = index - 1;
do
{
var c = json[index];
if ((c >= '0' && c <= '9') || c == '.' || c == '-' || c == '+' || c == 'e' || c == 'E')
{
if (++index == json.Length) throw new Exception("Unexpected end of string whilst parsing number");
continue;
}
break;
} while (true);
return new string(json, startIndex, index - startIndex);
}
private Token LookAhead()
{
if (lookAheadToken != Token.None) return lookAheadToken;
return lookAheadToken = NextTokenCore();
}
private void ConsumeToken()
{
lookAheadToken = Token.None;
}
private Token NextToken()
{
var result = lookAheadToken != Token.None ? lookAheadToken : NextTokenCore();
lookAheadToken = Token.None;
return result;
}
private Token NextTokenCore()
{
char c;
// Skip past whitespace
do
{
c = json[index];
if (c > ' ') break;
if (c != ' ' && c != '\t' && c != '\n' && c != '\r') break;
} while (++index < json.Length);
if (index == json.Length)
{
throw new Exception("Reached end of string unexpectedly");
}
c = json[index];
index++;
//if (c >= '0' && c <= '9')
// return Token.Number;
switch (c)
{
case '{':
return Token.Curly_Open;
case '}':
return Token.Curly_Close;
case '[':
return Token.Squared_Open;
case ']':
return Token.Squared_Close;
case ',':
return Token.Comma;
case '"':
return Token.String;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
case '-': case '+': case '.':
return Token.Number;
case ':':
return Token.Colon;
case 'f':
if (json.Length - index >= 4 &&
json[index + 0] == 'a' &&
json[index + 1] == 'l' &&
json[index + 2] == 's' &&
json[index + 3] == 'e')
{
index += 4;
return Token.False;
}
break;
case 't':
if (json.Length - index >= 3 &&
json[index + 0] == 'r' &&
json[index + 1] == 'u' &&
json[index + 2] == 'e')
{
index += 3;
return Token.True;
}
break;
case 'n':
if (json.Length - index >= 3 &&
json[index + 0] == 'u' &&
json[index + 1] == 'l' &&
json[index + 2] == 'l')
{
index += 3;
return Token.Null;
}
break;
}
throw new Exception("Could not find token at index " + --index);
}
}
}

View File

@ -0,0 +1,518 @@
//http://fastjson.codeplex.com/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Globalization;
using System.IO;
using System.Text;
namespace Exceptron.Driver.fastJSON
{
internal class JSONSerializer
{
private readonly StringBuilder _output = new StringBuilder();
readonly bool useMinimalDataSetSchema;
readonly bool fastguid = true;
readonly bool useExtension = true;
readonly bool serializeNulls = true;
readonly int _MAX_DEPTH = 10;
bool _Indent = false;
bool _useGlobalTypes = true;
int _current_depth = 0;
private Dictionary<string, int> _globalTypes = new Dictionary<string, int>();
internal JSONSerializer(bool UseMinimalDataSetSchema, bool UseFastGuid, bool UseExtensions, bool SerializeNulls, bool IndentOutput)
{
this.useMinimalDataSetSchema = UseMinimalDataSetSchema;
this.fastguid = UseFastGuid;
this.useExtension = UseExtensions;
_Indent = IndentOutput;
this.serializeNulls = SerializeNulls;
if (useExtension == false)
_useGlobalTypes = false;
}
internal string ConvertToJSON(object obj)
{
WriteValue(obj);
string str = "";
if (_useGlobalTypes)
{
StringBuilder sb = new StringBuilder();
sb.Append("{\"$types\":{");
bool pendingSeparator = false;
foreach (var kv in _globalTypes)
{
if (pendingSeparator) sb.Append(',');
pendingSeparator = true;
sb.Append("\"");
sb.Append(kv.Key);
sb.Append("\":\"");
sb.Append(kv.Value);
sb.Append("\"");
}
sb.Append("},");
str = sb.ToString() + _output.ToString();
}
else
str = _output.ToString();
return str;
}
private void WriteValue(object obj)
{
if (obj == null || obj is DBNull)
_output.Append("null");
else if (obj is string || obj is char)
WriteString((string)obj);
else if (obj is Guid)
WriteGuid((Guid)obj);
else if (obj is bool)
_output.Append(((bool)obj) ? "true" : "false"); // conform to standard
else if (
obj is int || obj is long || obj is double ||
obj is decimal || obj is float ||
obj is byte || obj is short ||
obj is sbyte || obj is ushort ||
obj is uint || obj is ulong
)
_output.Append(((IConvertible)obj).ToString(NumberFormatInfo.InvariantInfo));
else if (obj is DateTime)
WriteDateTime((DateTime)obj);
else if (obj is IDictionary && obj.GetType().IsGenericType && obj.GetType().GetGenericArguments()[0] == typeof(string))
WriteStringDictionary((IDictionary)obj);
else if (obj is IDictionary)
WriteDictionary((IDictionary)obj);
#if !SILVERLIGHT
else if (obj is DataSet)
WriteDataset((DataSet)obj);
else if (obj is DataTable)
this.WriteDataTable((DataTable)obj);
#endif
else if (obj is byte[])
WriteBytes((byte[])obj);
else if (obj is Array || obj is IList || obj is ICollection)
WriteArray((IEnumerable)obj);
else if (obj is Enum)
WriteEnum((Enum)obj);
#if CUSTOMTYPE
else if (JSON.Instance.IsTypeRegistered(obj.GetType()))
WriteCustom(obj);
#endif
else
WriteObject(obj);
}
#if CUSTOMTYPE
private void WriteCustom(object obj)
{
Serialize s;
JSON.Instance._customSerializer.TryGetValue(obj.GetType(), out s);
WriteStringFast(s(obj));
}
#endif
private void WriteEnum(Enum e)
{
// TODO : optimize enum write
WriteStringFast(e.ToString());
}
private void WriteGuid(Guid g)
{
if (fastguid == false)
WriteStringFast(g.ToString());
else
WriteBytes(g.ToByteArray());
}
private void WriteBytes(byte[] bytes)
{
#if !SILVERLIGHT
WriteStringFast(Convert.ToBase64String(bytes, 0, bytes.Length, Base64FormattingOptions.None));
#else
WriteStringFast(Convert.ToBase64String(bytes, 0, bytes.Length));
#endif
}
private void WriteDateTime(DateTime dateTime)
{
// datetime format standard : yyyy-MM-dd HH:mm:ss
DateTime dt = dateTime;
if (JSON.Instance.UseUTCDateTime)
dt = dateTime.ToUniversalTime();
_output.Append("\"");
_output.Append(dt.Year.ToString("0000", NumberFormatInfo.InvariantInfo));
_output.Append("-");
_output.Append(dt.Month.ToString("00", NumberFormatInfo.InvariantInfo));
_output.Append("-");
_output.Append(dt.Day.ToString("00", NumberFormatInfo.InvariantInfo));
_output.Append(" ");
_output.Append(dt.Hour.ToString("00", NumberFormatInfo.InvariantInfo));
_output.Append(":");
_output.Append(dt.Minute.ToString("00", NumberFormatInfo.InvariantInfo));
_output.Append(":");
_output.Append(dt.Second.ToString("00", NumberFormatInfo.InvariantInfo));
if (JSON.Instance.UseUTCDateTime)
_output.Append("Z");
_output.Append("\"");
}
#if !SILVERLIGHT
private DatasetSchema GetSchema(DataTable ds)
{
if (ds == null) return null;
DatasetSchema m = new DatasetSchema();
m.Info = new List<string>();
m.Name = ds.TableName;
foreach (DataColumn c in ds.Columns)
{
m.Info.Add(ds.TableName);
m.Info.Add(c.ColumnName);
m.Info.Add(c.DataType.ToString());
}
// TODO : serialize relations and constraints here
return m;
}
private DatasetSchema GetSchema(DataSet ds)
{
if (ds == null) return null;
DatasetSchema m = new DatasetSchema();
m.Info = new List<string>();
m.Name = ds.DataSetName;
foreach (DataTable t in ds.Tables)
{
foreach (DataColumn c in t.Columns)
{
m.Info.Add(t.TableName);
m.Info.Add(c.ColumnName);
m.Info.Add(c.DataType.ToString());
}
}
// TODO : serialize relations and constraints here
return m;
}
private string GetXmlSchema(DataTable dt)
{
using (var writer = new StringWriter())
{
dt.WriteXmlSchema(writer);
return dt.ToString();
}
}
private void WriteDataset(DataSet ds)
{
_output.Append('{');
if (useExtension)
{
WritePair("$schema", useMinimalDataSetSchema ? (object)GetSchema(ds) : ds.GetXmlSchema());
_output.Append(',');
}
bool tablesep = false;
foreach (DataTable table in ds.Tables)
{
if (tablesep) _output.Append(",");
tablesep = true;
WriteDataTableData(table);
}
// end dataset
_output.Append('}');
}
private void WriteDataTableData(DataTable table)
{
_output.Append('\"');
_output.Append(table.TableName);
_output.Append("\":[");
DataColumnCollection cols = table.Columns;
bool rowseparator = false;
foreach (DataRow row in table.Rows)
{
if (rowseparator) _output.Append(",");
rowseparator = true;
_output.Append('[');
bool pendingSeperator = false;
foreach (DataColumn column in cols)
{
if (pendingSeperator) _output.Append(',');
WriteValue(row[column]);
pendingSeperator = true;
}
_output.Append(']');
}
_output.Append(']');
}
void WriteDataTable(DataTable dt)
{
this._output.Append('{');
if (this.useExtension)
{
this.WritePair("$schema", this.useMinimalDataSetSchema ? (object)this.GetSchema(dt) : this.GetXmlSchema(dt));
this._output.Append(',');
}
WriteDataTableData(dt);
// end datatable
this._output.Append('}');
}
#endif
bool _firstWritten = false;
private void WriteObject(object obj)
{
Indent();
if (_useGlobalTypes == false)
_output.Append('{');
else
{
if (_firstWritten)
_output.Append("{");
}
_firstWritten = true;
_current_depth++;
if (_current_depth > _MAX_DEPTH)
throw new Exception("Serializer encountered maximum depth of " + _MAX_DEPTH);
Dictionary<string, string> map = new Dictionary<string, string>();
Type t = obj.GetType();
bool append = false;
if (useExtension)
{
if (_useGlobalTypes == false)
WritePairFast("$type", JSON.Instance.GetTypeAssemblyName(t));
else
{
int dt = 0;
string ct = JSON.Instance.GetTypeAssemblyName(t);
if (_globalTypes.TryGetValue(ct, out dt) == false)
{
dt = _globalTypes.Count + 1;
_globalTypes.Add(ct, dt);
}
WritePairFast("$type", dt.ToString());
}
append = true;
}
List<Getters> g = JSON.Instance.GetGetters(t);
foreach (var p in g)
{
if (append)
_output.Append(',');
object o = p.Getter(obj);
if ((o == null || o is DBNull) && serializeNulls == false)
append = false;
else
{
WritePair(p.Name, o);
if (o != null && useExtension)
{
Type tt = o.GetType();
if (tt == typeof(System.Object))
map.Add(p.Name, tt.ToString());
}
append = true;
}
}
if (map.Count > 0 && useExtension)
{
_output.Append(",\"$map\":");
WriteStringDictionary(map);
}
_current_depth--;
Indent();
_output.Append('}');
_current_depth--;
}
private void Indent()
{
Indent(false);
}
private void Indent(bool dec)
{
if (_Indent)
{
_output.Append("\r\n");
for (int i = 0; i < _current_depth - (dec ? 1 : 0); i++)
_output.Append("\t");
}
}
private void WritePairFast(string name, string value)
{
if ((value == null) && serializeNulls == false)
return;
Indent();
WriteStringFast(name);
_output.Append(':');
WriteStringFast(value);
}
private void WritePair(string name, object value)
{
if ((value == null || value is DBNull) && serializeNulls == false)
return;
Indent();
WriteStringFast(name);
_output.Append(':');
WriteValue(value);
}
private void WriteArray(IEnumerable array)
{
Indent();
_output.Append('[');
bool pendingSeperator = false;
foreach (object obj in array)
{
Indent();
if (pendingSeperator) _output.Append(',');
WriteValue(obj);
pendingSeperator = true;
}
Indent();
_output.Append(']');
}
private void WriteStringDictionary(IDictionary dic)
{
Indent();
_output.Append('{');
bool pendingSeparator = false;
foreach (DictionaryEntry entry in dic)
{
if (pendingSeparator) _output.Append(',');
WritePair((string)entry.Key, entry.Value);
pendingSeparator = true;
}
Indent();
_output.Append('}');
}
private void WriteDictionary(IDictionary dic)
{
Indent();
_output.Append('[');
bool pendingSeparator = false;
foreach (DictionaryEntry entry in dic)
{
if (pendingSeparator) _output.Append(',');
Indent();
_output.Append('{');
WritePair("k", entry.Key);
_output.Append(",");
WritePair("v", entry.Value);
Indent();
_output.Append('}');
pendingSeparator = true;
}
Indent();
_output.Append(']');
}
private void WriteStringFast(string s)
{
//Indent();
_output.Append('\"');
_output.Append(s);
_output.Append('\"');
}
private void WriteString(string s)
{
//Indent();
_output.Append('\"');
int runIndex = -1;
for (var index = 0; index < s.Length; ++index)
{
var c = s[index];
if (c >= ' ' && c < 128 && c != '\"' && c != '\\')
{
if (runIndex == -1)
{
runIndex = index;
}
continue;
}
if (runIndex != -1)
{
_output.Append(s, runIndex, index - runIndex);
runIndex = -1;
}
switch (c)
{
case '\t': _output.Append("\\t"); break;
case '\r': _output.Append("\\r"); break;
case '\n': _output.Append("\\n"); break;
case '"':
case '\\': _output.Append('\\'); _output.Append(c); break;
default:
_output.Append("\\u");
_output.Append(((int)c).ToString("X4", NumberFormatInfo.InvariantInfo));
break;
}
}
if (runIndex != -1)
{
_output.Append(s, runIndex, s.Length - runIndex);
}
_output.Append('\"');
}
}
}

View File

@ -0,0 +1,39 @@
//http://fastjson.codeplex.com/
using System.Collections.Generic;
namespace Exceptron.Driver.fastJSON
{
internal class SafeDictionary<TKey, TValue>
{
private readonly object _Padlock = new object();
private readonly Dictionary<TKey, TValue> _Dictionary = new Dictionary<TKey, TValue>();
public bool TryGetValue(TKey key, out TValue value)
{
return _Dictionary.TryGetValue(key, out value);
}
public TValue this[TKey key]
{
get
{
return _Dictionary[key];
}
}
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
{
return ((ICollection<KeyValuePair<TKey, TValue>>)_Dictionary).GetEnumerator();
}
public void Add(TKey key, TValue value)
{
lock (_Padlock)
{
if (_Dictionary.ContainsKey(key) == false)
_Dictionary.Add(key, value);
}
}
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff