diff --git a/NzbDrone.Common/NzbDrone.Common.csproj b/NzbDrone.Common/NzbDrone.Common.csproj
index bb0d799f1..459787216 100644
--- a/NzbDrone.Common/NzbDrone.Common.csproj
+++ b/NzbDrone.Common/NzbDrone.Common.csproj
@@ -36,13 +36,11 @@
..\Libraries\Exceptioneer.WindowsFormsClient.dll
-
- False
- ..\packages\Exceptrack.Driver.0.1.0.3\lib\net20\Exceptrack.Driver.dll
+
+ ..\packages\Exceptron.Driver.0.1.0.3\lib\net20\Exceptron.Driver.dll
- False
- ..\packages\Newtonsoft.Json.4.5.3\lib\net40\Newtonsoft.Json.dll
+ ..\packages\Newtonsoft.Json.4.5.4\lib\net40\Newtonsoft.Json.dll
..\packages\Ninject.2.2.1.4\lib\net40-Full\Ninject.dll
diff --git a/NzbDrone.Common/ReportingService.cs b/NzbDrone.Common/ReportingService.cs
index 1820040d2..4f6a95431 100644
--- a/NzbDrone.Common/ReportingService.cs
+++ b/NzbDrone.Common/ReportingService.cs
@@ -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 parserErrorCache = new HashSet();
@@ -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.");
}
}
}
diff --git a/NzbDrone.Common/packages.config b/NzbDrone.Common/packages.config
index 0a89dc639..855d77fe3 100644
--- a/NzbDrone.Common/packages.config
+++ b/NzbDrone.Common/packages.config
@@ -1,6 +1,6 @@
-
-
+
+
\ No newline at end of file
diff --git a/NzbDrone.Core.Test/Framework/CoreTest.cs b/NzbDrone.Core.Test/Framework/CoreTest.cs
index dae211d40..9f63d02f7 100644
--- a/NzbDrone.Core.Test/Framework/CoreTest.cs
+++ b/NzbDrone.Core.Test/Framework/CoreTest.cs
@@ -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()
{
diff --git a/NzbDrone.Core.Test/Integeration/ServiceIntegerationFixture.cs b/NzbDrone.Core.Test/Integeration/ServiceIntegerationFixture.cs
index 9e95e5365..7e310d018 100644
--- a/NzbDrone.Core.Test/Integeration/ServiceIntegerationFixture.cs
+++ b/NzbDrone.Core.Test/Integeration/ServiceIntegerationFixture.cs
@@ -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);
}
diff --git a/NzbDrone.Core/CentralDispatch.cs b/NzbDrone.Core/CentralDispatch.cs
index fd241be8f..09b5e91ad 100644
--- a/NzbDrone.Core/CentralDispatch.cs
+++ b/NzbDrone.Core/CentralDispatch.cs
@@ -68,7 +68,7 @@ namespace NzbDrone.Core
{
EnvironmentProvider.UGuid = Kernel.Get().UGuid;
ReportingService.RestProvider = Kernel.Get();
- ReportingService.SetupExceptrackDriver();
+ ReportingService.SetupExceptronDriver();
var appId = AnalyticsProvider.DESKMETRICS_TEST_ID;
diff --git a/NzbDrone.Test.Common/TestBase.cs b/NzbDrone.Test.Common/TestBase.cs
index 8eead930a..b67718ece 100644
--- a/NzbDrone.Test.Common/TestBase.cs
+++ b/NzbDrone.Test.Common/TestBase.cs
@@ -49,7 +49,7 @@ namespace NzbDrone.Test.Common
MockedRestProvider = new Mock();
ReportingService.RestProvider = MockedRestProvider.Object;
- ReportingService.SetupExceptrackDriver();
+ ReportingService.SetupExceptronDriver();
if (Directory.Exists(TempFolder))
diff --git a/NzbDrone.Update/Program.cs b/NzbDrone.Update/Program.cs
index b3030c3ba..6b9ffdb9e 100644
--- a/NzbDrone.Update/Program.cs
+++ b/NzbDrone.Update/Program.cs
@@ -62,7 +62,7 @@ namespace NzbDrone.Update
private static void InitLoggers()
{
ReportingService.RestProvider = _kernel.Get();
- ReportingService.SetupExceptrackDriver();
+ ReportingService.SetupExceptronDriver();
LogConfiguration.RegisterRemote();
diff --git a/NzbDrone/CentralDispatch.cs b/NzbDrone/CentralDispatch.cs
index 33e7a92cc..f0c3e45f1 100644
--- a/NzbDrone/CentralDispatch.cs
+++ b/NzbDrone/CentralDispatch.cs
@@ -46,7 +46,7 @@ namespace NzbDrone
var environmentProvider = _kernel.Get();
ReportingService.RestProvider = _kernel.Get();
- ReportingService.SetupExceptrackDriver();
+ ReportingService.SetupExceptronDriver();
LogConfiguration.RegisterRollingFileLogger(environmentProvider.GetLogFileName(), LogLevel.Info);
LogConfiguration.RegisterConsoleLogger(LogLevel.Debug);
diff --git a/packages/Exceptrack.Driver.0.1.0.3/Exceptrack.Driver.0.1.0.3.nupkg b/packages/Exceptrack.Driver.0.1.0.3/Exceptrack.Driver.0.1.0.3.nupkg
deleted file mode 100644
index 1ad583875..000000000
Binary files a/packages/Exceptrack.Driver.0.1.0.3/Exceptrack.Driver.0.1.0.3.nupkg and /dev/null differ
diff --git a/packages/Exceptrack.Driver.0.1.0.3/lib/net20/Exceptrack.Driver.dll b/packages/Exceptrack.Driver.0.1.0.3/lib/net20/Exceptrack.Driver.dll
deleted file mode 100644
index 67b13d5f9..000000000
Binary files a/packages/Exceptrack.Driver.0.1.0.3/lib/net20/Exceptrack.Driver.dll and /dev/null differ
diff --git a/packages/Exceptron.Driver.0.1.0.3/Exceptron.Driver.0.1.0.3.nupkg b/packages/Exceptron.Driver.0.1.0.3/Exceptron.Driver.0.1.0.3.nupkg
new file mode 100644
index 000000000..99a62c50d
Binary files /dev/null and b/packages/Exceptron.Driver.0.1.0.3/Exceptron.Driver.0.1.0.3.nupkg differ
diff --git a/packages/Exceptron.Driver.0.1.0.3/lib/net20/Exceptron.Driver.dll b/packages/Exceptron.Driver.0.1.0.3/lib/net20/Exceptron.Driver.dll
new file mode 100644
index 000000000..c42f7ec7f
Binary files /dev/null and b/packages/Exceptron.Driver.0.1.0.3/lib/net20/Exceptron.Driver.dll differ
diff --git a/packages/Exceptron.Driver.0.1.0.3/lib/net20/Exceptron.Driver.pdb b/packages/Exceptron.Driver.0.1.0.3/lib/net20/Exceptron.Driver.pdb
new file mode 100644
index 000000000..dda2a7564
Binary files /dev/null and b/packages/Exceptron.Driver.0.1.0.3/lib/net20/Exceptron.Driver.pdb differ
diff --git a/packages/Exceptron.Driver.0.1.0.3/src/ExceptionClient.cs b/packages/Exceptron.Driver.0.1.0.3/src/ExceptionClient.cs
new file mode 100644
index 000000000..369648f28
--- /dev/null
+++ b/packages/Exceptron.Driver.0.1.0.3/src/ExceptionClient.cs
@@ -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 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();
+
+ 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;
+ }
+ }
+}
diff --git a/packages/Exceptron.Driver.0.1.0.3/src/ExceptionData.cs b/packages/Exceptron.Driver.0.1.0.3/src/ExceptionData.cs
new file mode 100644
index 000000000..20fda0172
--- /dev/null
+++ b/packages/Exceptron.Driver.0.1.0.3/src/ExceptionData.cs
@@ -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; }
+ }
+}
\ No newline at end of file
diff --git a/packages/Exceptron.Driver.0.1.0.3/src/ExceptionReport.cs b/packages/Exceptron.Driver.0.1.0.3/src/ExceptionReport.cs
new file mode 100644
index 000000000..a645a2941
--- /dev/null
+++ b/packages/Exceptron.Driver.0.1.0.3/src/ExceptionReport.cs
@@ -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 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; }
+ }
+}
\ No newline at end of file
diff --git a/packages/Exceptron.Driver.0.1.0.3/src/Frame.cs b/packages/Exceptron.Driver.0.1.0.3/src/Frame.cs
new file mode 100644
index 000000000..263d40d34
--- /dev/null
+++ b/packages/Exceptron.Driver.0.1.0.3/src/Frame.cs
@@ -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; }
+ }
+}
\ No newline at end of file
diff --git a/packages/Exceptron.Driver.0.1.0.3/src/Properties/AssemblyInfo.cs b/packages/Exceptron.Driver.0.1.0.3/src/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..349b74fee
--- /dev/null
+++ b/packages/Exceptron.Driver.0.1.0.3/src/Properties/AssemblyInfo.cs
@@ -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")]
diff --git a/packages/Exceptron.Driver.0.1.0.3/src/fastJSON/Getters.cs b/packages/Exceptron.Driver.0.1.0.3/src/fastJSON/Getters.cs
new file mode 100644
index 000000000..5263a13bc
--- /dev/null
+++ b/packages/Exceptron.Driver.0.1.0.3/src/fastJSON/Getters.cs
@@ -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 Info { get; set; }
+ public string Name { get; set; }
+ }
+}
diff --git a/packages/Exceptron.Driver.0.1.0.3/src/fastJSON/JSON.cs b/packages/Exceptron.Driver.0.1.0.3/src/fastJSON/JSON.cs
new file mode 100644
index 000000000..aae0142a8
--- /dev/null
+++ b/packages/Exceptron.Driver.0.1.0.3/src/fastJSON/JSON.cs
@@ -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(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 ht = new JsonParser(json).Decode() as Dictionary;
+ if (ht == null) return null;
+ return ParseDictionary(ht, null, type);
+ }
+
+#if CUSTOMTYPE
+ internal SafeDictionary _customSerializer = new SafeDictionary();
+ internal SafeDictionary _customDeserializer = new SafeDictionary();
+
+ 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>();
+ }
+ }
+
+ internal bool IsTypeRegistered(Type t)
+ {
+ Serialize s;
+ return _customSerializer.TryGetValue(t, out s);
+ }
+#endif
+
+ #region [ PROPERTY GET SET CACHE ]
+ SafeDictionary _tyname = new SafeDictionary();
+ 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 _typecache = new SafeDictionary();
+ 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 _constrcache = new SafeDictionary();
+ 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> _propertycache = new SafeDictionary>();
+ private SafeDictionary Getproperties(Type type, string typename)
+ {
+ SafeDictionary sd = null;
+ if (_propertycache.TryGetValue(typename, out sd))
+ {
+ return sd;
+ }
+ else
+ {
+ sd = new SafeDictionary();
+ 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> _getterscache = new SafeDictionary>();
+ internal List GetGetters(Type type)
+ {
+ List val = null;
+ if (_getterscache.TryGetValue(type, out val))
+ return val;
+
+ PropertyInfo[] props = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
+ List getters = new List();
+ 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 d, Dictionary globaltypes, Type type)
+ {
+ object tn = "";
+ if (d.TryGetValue("$types", out tn))
+ {
+ UsingGlobalTypes = true;
+ globaltypes = new Dictionary();
+ foreach (var kv in (Dictionary)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 props = Getproperties(type, typename);
+ foreach (string name in d.Keys)
+ {
+ if (name == "$map")
+ {
+ ProcessMap(o, props, (Dictionary)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