/// <summary>
        /// Gets the base64 encoded string for the given icon resource url. This method has the potential to be very slow
        /// as it will create a new resourceManager for a given assembly and search that assembly, which may require disk access.
        /// </summary>
        /// <param name="icon">Icon Url</param>
        /// <param name="extension">Returns the extension to describe the type of resource.</param>
        /// <returns>a base64 encoded string version of an image if found else null.</returns>
        private string GetIconAsBase64(IconUrl icon, out string extension)
        {
            extension = "png";

            var path = Path.GetFullPath(icon.Path); //Get full path if it's a relative path.
            var libraryCustomization = getForAssemblyMethodInfo.Invoke(null, new object[] { path, pathManager, true });

            if (libraryCustomization == null)
            {
                return(null);
            }

            var assembly = LibraryCustomizationResourceAssemblyProperty.GetValue(libraryCustomization) as Assembly;

            if (assembly == null)
            {
                return(null);
            }

            // "Name" can be "Some.Assembly.Name.customization" with multiple dots,
            // we are interested in removal of the "customization" part and the middle dots.
            var temp         = assembly.GetName().Name.Split('.');
            var assemblyName = String.Join("", temp.Take(temp.Length - 1));
            var rm           = new ResourceManager(assemblyName + imagesSuffix, assembly);

            using (var image = (Bitmap)rm.GetObject(icon.Name))
            {
                if (image == null)
                {
                    return(null);
                }

                var tempstream = new MemoryStream();

                image.Save(tempstream, image.RawFormat);
                byte[] imageBytes = tempstream.ToArray();
                tempstream.Dispose();
                string base64String = Convert.ToBase64String(imageBytes);
                return(base64String);
            }
        }
        /// <summary>
        /// Retrieves the resource for a given url as a base64 encoded string.
        /// ie data:image/png;base64, stringxxxyyyzzz
        /// </summary>
        /// <param name="url">url for the requested icon</param>
        /// <param name="extension">Returns the extension to describe the type of resource.</param>
        /// <returns></returns>
        public string GetResourceAsString(string url, out string extension)
        {
            //sometimes the urls have "about:" added to them - remove this
            //and do it before checking cache.
            //https://en.wikipedia.org/wiki/About_URI_scheme
            if (url.StartsWith("about:"))
            {
                url = url?.Replace("about:", string.Empty);
            }

            if (!String.IsNullOrEmpty(url) && urlToBase64DataCache.ContainsKey(url))
            {
                var cachedData = urlToBase64DataCache[url];
                extension = cachedData.Item2;
                return(cachedData.Item1);
            }

            //because we modify the spec the icon urls may have been replaced by base64 encoded images
            //if thats the case, no need to look them up again from disk, just return the string.
            if (!String.IsNullOrEmpty(url) && url.Contains("data:image/"))
            {
                var match       = Regex.Match(url, @"data:(?<type>.+?);base64,(?<data>.+)");
                var base64Data  = match.Groups["data"].Value;
                var contentType = match.Groups["type"].Value;
                //image/png -> png
                extension = contentType.Split('/').Skip(1).FirstOrDefault();
                urlToBase64DataCache.Add(url, Tuple.Create(base64Data, extension));
                return(base64Data);
            }


            var base64String = string.Empty;

            extension = "png";
            //Create IconUrl to parse the request.Url to icon name and path.
            if (String.IsNullOrEmpty(url))
            {
                return(string.Empty);
            }

            //before trying to create a uri we have to handle resources that might
            //be embedded into the resources.dlls
            //these paths will start with ./dist
            if (url.StartsWith(@"./dist"))
            {
                //make relative url a full uri
                var urlAbs = url.Replace(@"./dist", @"http://localhost/dist");
                var ext    = string.Empty;
                var stream = embeddedDllResourceProvider.GetResource(urlAbs, out ext);
                if (stream != null)
                {
                    extension    = ext;
                    base64String = GetIconAsBase64(stream, ext);
                }
            }
            else
            {
                //TODO check if absolute instead of using try/catch
                try
                {
                    var icon = new IconUrl(new Uri(url));
                    base64String = GetIconAsBase64(icon, out extension);
                }
                catch (Exception)
                {
                    //look in resources for registered path and just use the stream directly
                    var resourceDict = this.customization.Resources.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
                    if (resourceDict.ContainsKey(url))
                    {
                        var fileExtension = System.IO.Path.GetExtension(url);
                        extension    = fileExtension;
                        base64String = GetIconAsBase64(resourceDict[url], fileExtension);
                    }
                }
            }
            if (base64String == null)
            {
                base64String = GetDefaultIconBase64(out extension);
            }
            urlToBase64DataCache.Add(url, Tuple.Create(base64String, extension));
            return(base64String);
        }