public static Module ToModuleInfo(this Assembly assembly, IExceptionlessLog log = null) {
            if (assembly == null)
                return null;

            if (log == null)
                log = new NullExceptionlessLog();

            Module module = _moduleCache.GetOrAdd(assembly.FullName, k => {
                var mod = new Module();
                AssemblyName name = assembly.GetAssemblyName();
                if (name != null) {
                    mod.Name = name.Name;
                    mod.Version = name.Version.ToString();
                    byte[] pkt = name.GetPublicKeyToken();
                    if (pkt.Length > 0)
                        mod.Data["PublicKeyToken"] = pkt.ToHex();
                }

                string infoVersion = assembly.GetInformationalVersion();
                if (!String.IsNullOrEmpty(infoVersion) && infoVersion != mod.Version)
                    mod.Data["ProductVersion"] = infoVersion;

                string fileVersion = assembly.GetFileVersion();
                if (!String.IsNullOrEmpty(fileVersion) && fileVersion != mod.Version)
                    mod.Data["FileVersion"] = fileVersion;

                DateTime? creationTime = assembly.GetCreationTime();
                if (creationTime.HasValue)
                    mod.CreatedDate = creationTime.Value;

                DateTime? lastWriteTime = assembly.GetLastWriteTime();
                if (lastWriteTime.HasValue)
                    mod.ModifiedDate = lastWriteTime.Value;

                return mod;
            });

            if (module != null) {
                if (assembly == Assembly.GetEntryAssembly())
                    module.IsEntry = true;
            }

            return module;
        }
        /// <summary>
        /// Sets the properties from an exception.
        /// </summary>
        /// <param name="exception">The exception to populate properties from.</param>
        /// <param name="log">The log implementation used for diagnostic information.</param>
        public static Error ToErrorModel(this Exception exception
#if EMBEDDED
            , IExceptionlessLog log = null
#endif
            ) {
            if (exception == null)
                throw new ArgumentNullException("exception");

#if EMBEDDED
            if (log == null)
                log = new NullExceptionlessLog();
#endif

            Type type = exception.GetType();

            var error = new Error {
                Message = exception.GetMessage(),
#if EMBEDDED
                Modules = GetLoadedModules(log),
#else
                Modules = GetLoadedModules(),
#endif
                Type = type.FullName
            };
            error.PopulateStackTrace(error, exception);

#if !SILVERLIGHT
            try {
                PropertyInfo info = type.GetProperty("HResult", BindingFlags.NonPublic | BindingFlags.Instance);
                if (info != null)
                    error.Code = info.GetValue(exception, null).ToString();
            } catch (Exception) {}
#endif

            if (exception.TargetSite != null) {
                error.TargetMethod = new Method();
                error.TargetMethod.PopulateMethod(error, exception.TargetSite);
            }

            // TODO: Test adding non-serializable objects to ExtendedData and see what happens
            try {
                Dictionary<string, object> extraProperties = type.GetPublicProperties().Where(p => !_exceptionExclusions.Contains(p.Name)).ToDictionary(p => p.Name, p => {
                    try {
                        return p.GetValue(exception, null);
                    } catch {}
                    return null;
                });

                extraProperties = extraProperties.Where(kvp => !ValueIsEmpty(kvp.Value)).ToDictionary(kvp => kvp.Key, kvp => kvp.Value);

                if (extraProperties.Count > 0 && !error.ExtendedData.ContainsKey(ExtendedDataDictionary.EXCEPTION_INFO_KEY)) {
                    error.AddObject(new ExtendedDataInfo {
                        Data = extraProperties,
                        Name = ExtendedDataDictionary.EXCEPTION_INFO_KEY,
                        IgnoreSerializationErrors = true,
                        MaxDepthToSerialize = 5
                    });
                }
            } catch {}

            if (exception.InnerException != null)
                error.Inner = exception.InnerException.ToErrorModel();

            return error;
        }