/// <summary> /// Gets the file data for the specified resource, storing a cached version if specified. /// IMPORTANT: /// NOTE: Make sure any and all await calls inside this function and its children /// use ConfigureAwait(false). This is because the parent has to support /// a synchronous version of this call, so the method cannot sync back with /// its calling context without risk of deadlock. /// </summary> /// <param name="pathFormat">The path to the desired resource, containing {0} in place of the culture</param> /// <param name="constructData">The function that takes the file data and converts it into the format required by the provider</param> /// <param name="culture">The culture to use. If not specified, the default culture is used</param> /// <returns></returns> protected async Task <T> GetResourceDocumentAsync <T>(ResourceDefinition pathFormat, Func <Stream, T> constructData, string culture = null) { try { await mSelfLock.WaitAsync(); // Get culture path var resourcePath = ResourceFormatProviderHelpers.GetCulturePath(pathFormat.Location, culture); // Make sure list has been initialized if (mCache == null) { mCache = new Dictionary <string, object>(); } // If we have a document already, return that if (mCache.ContainsKey(resourcePath)) { return((T)mCache[resourcePath]); } // Otherwise try and get it var resourceDocument = default(T); try { // Try to get the stream for this resource using (var stream = await ResourceFormatProviderHelpers.GetStreamAsync(pathFormat.Type, resourcePath).ConfigureAwait(false)) { // If successful, try and convert that data into a usable resource object if (stream != null) { resourceDocument = constructData(stream); } } } finally { // Add resource document if found or not (except for Urls, never add failed Urls in case of bad Internet connection if (mCacheResourceFiles && pathFormat.Type != ResourceDefinitionType.Url) { mCache.Add(resourcePath, resourceDocument); } } // Return what we found, if anything return(resourceDocument); } finally { mSelfLock.Release(); } }
/// <summary> /// Gets the format of this resource /// </summary> /// <param name="resourceDefinition">The resource definition</param> /// <returns></returns> public static string GetFormat(ResourceDefinition resourceDefinition) { var extension = resourceDefinition.ExplicitFormat; // If not, get it from the file extension if (string.IsNullOrEmpty(resourceDefinition.ExplicitFormat)) { extension = Path.GetExtension(resourceDefinition.Location); if (extension != null && extension.StartsWith(".")) { extension = extension.Substring(1); } } return(extension); }
/// <summary> /// Finds a string of the given name, taking into account the culture information. /// If no culture is specified, the default culture is used /// /// IMPORTANT: /// NOTE: Make sure any and all await calls inside this function and its children /// use ConfigureAwait(false). This is because the parent has to support /// a synchronous version of this call, so the method cannot sync back with /// its calling context without risk of deadlock. /// </summary> public async Task <bool> GetStringAsync(ResourceDefinition resource, string name, string culture, Action <string> onResult) { // Get string document for this culture var document = await GetResourceDocumentAsync(resource, XDocument.Load, culture).ConfigureAwait(false); // If it is null, try and find the default culture if specified if (document == null) { if (resource.UseDefaultCultureIfNotFound) { document = await GetResourceDocumentAsync(resource, XDocument.Load).ConfigureAwait(false); } // Document not found so return false if (document == null) { return(false); } } // Null check for root document if (document.Root == null) { return(false); } // Get the first element that matches the given name (ignore case) var element = document.Root.Elements().FirstOrDefault( f => f.Attributes().Any(a => a.Name.LocalName == "Name") && string.Equals(name, f.Attributes().First(a => a.Name.LocalName == "Name").Value, StringComparison.CurrentCultureIgnoreCase)); // Return false if not found if (element == null) { return(false); } // Otherwise we found the value so return it onResult(element.Value); return(true); }