using System; using System.Reflection; using System.IO; using System.Threading.Tasks; using System.Collections.Generic; namespace SBRL.Utilities { /// /// A collection of static methods for manipulating embedded resources. /// /// /// From https://gist.github.com/sbrl/aabfcfe87396b8c05d3263887b807d23. You may have seen /// this in several other ACWs I've done. Proof I wrote this is available upon request, /// of course. /// /// v0.6.2, by Starbeamrainbowlabs /// Last updated 28th November 2018. /// Licensed under MPL-2.0. /// /// Changelog: /// v0.1 (25th July 2016): /// - Initial release. /// v0.2 (8th August 2016): /// - Changed namespace. /// v0.3 (21st January 2017): /// - Added GetRawReader(). /// v0.4 (8th April 2017): /// - Removed unnecessary using statement. /// v0.5 (3rd September 2017): /// - Changed namespace /// v0.6 (12th October 2018): /// - Fixed assembly / calling assembly bugs /// v0.6.1 (17th october 2018): /// - Fix crash in ReadAllText(filename) /// v0.6.2 (28th November 2018): /// - Fix assembly targeting bug in ReadAllBytesAsync() /// public static class EmbeddedFiles { /// /// An array of the filenames of all the resources embedded in the target assembly. /// /// The target assembly to extract a resource list for. /// The resource list. public static string[] ResourceList(Assembly targetAssembly) { return targetAssembly.GetManifestResourceNames(); } /// /// An array of the filenames of all the resources embedded in the calling assembly. /// /// The resource list. public static string[] ResourceList() { return ResourceList(Assembly.GetCallingAssembly()); } /// /// Gets a list of resources embedded in the calling assembly as a string. /// public static string GetResourceListText() { return GetResourceListText(Assembly.GetCallingAssembly()); } /// /// Gets a list of resources embedded in the target assembly as a string. /// /// The target assembly to extract a resource list from. public static string GetResourceListText(Assembly targetAssembly) { StringWriter result = new StringWriter(); result.WriteLine("Files embedded in {0}:", targetAssembly.GetName().Name); foreach (string filename in ResourceList(targetAssembly)) result.WriteLine(" - {0}", filename); return result.ToString(); } /// /// Writes a list of resources embedded in the calling assembly to the standard output. /// public static void WriteResourceList() { Console.WriteLine(GetResourceListText(Assembly.GetCallingAssembly())); } /// /// Gets a StreamReader attached to the specified embedded resource. /// /// The filename of the embedded resource to get a StreamReader of. /// A StreamReader attached to the specified embedded resource. public static StreamReader GetReader(string filename) { return new StreamReader(GetRawReader(filename)); } /// /// Gets a raw Stream that's attached to the specified embedded resource /// in the calling assembly. /// Useful when you want to copy an embedded resource to some other stream. /// /// The path to the embedded resource. /// A raw Stream object attached to the specified file. public static Stream GetRawReader(string filename) { return GetRawReader(Assembly.GetCallingAssembly(), filename); } /// /// Gets a raw Stream that's attached to the specified embedded resource /// in the specified assembly. /// Useful when you want to copy an embedded resource to some other stream. /// /// The assembly to search for the filename in. /// The path to the embedded resource. /// A raw Stream object attached to the specified file. public static Stream GetRawReader(Assembly targetAssembly, string filename) { return targetAssembly.GetManifestResourceStream(filename); } /// /// Gets the specified embedded resource's content as a byte array. /// /// The filename of the embedded resource to get conteent of. /// The specified embedded resource's content as a byte array. public static byte[] ReadAllBytes(string filename) { // Referencing the Result property will block until the async method completes return ReadAllBytesAsync(filename).Result; } /// /// Gets the content of the resource that's embedded in the specified /// assembly as a byte array asynchronously. /// /// The assembly to search for the file in. /// The filename of the embedded resource to get content of. /// The specified embedded resource's content as a byte array. public static async Task ReadAllBytesAsync(Assembly targetAssembly, string filename) { using (Stream resourceStream = targetAssembly.GetManifestResourceStream(filename)) using (MemoryStream temp = new MemoryStream()) { await resourceStream.CopyToAsync(temp); return temp.ToArray(); } } public static async Task ReadAllBytesAsync(string filename) { return await ReadAllBytesAsync(Assembly.GetCallingAssembly(), filename); } /// /// Gets all the text stored in the resource that's embedded in the /// calling assembly. /// /// The filename to fetch the content of. /// All the text stored in the specified embedded resource. public static string ReadAllText(string filename) { return ReadAllTextAsync(Assembly.GetCallingAssembly(), filename).Result; } /// /// Gets all the text stored in the resource that's embedded in the /// specified assembly. /// /// The assembly from in which to look for the target embedded resource. /// The filename to fetch the content of. /// All the text stored in the specified embedded resource. public static string ReadAllText(Assembly targetAssembly, string filename) { return ReadAllTextAsync(targetAssembly, filename).Result; } /// /// Gets all the text stored in the resource that's embedded in the /// specified assembly asynchronously. /// /// The filename to fetch the content of. /// All the text stored in the specified embedded resource. public static async Task ReadAllTextAsync(Assembly targetAssembly, string filename) { using (StreamReader resourceReader = new StreamReader(targetAssembly.GetManifestResourceStream(filename))) { return await resourceReader.ReadToEndAsync(); } } /// /// Gets all the text stored in the resource that's embedded in the /// calling assembly asynchronously. /// /// The filename to fetch the content of. /// All the text stored in the specified embedded resource. public static async Task ReadAllTextAsync(string filename) { return await ReadAllTextAsync(Assembly.GetCallingAssembly(), filename); } /// /// Enumerates the lines of text in the embedded resource that's /// embedded in the calling assembly. /// /// The filename of the embedded resource to enumerate. /// An IEnumerator that enumerates the specified embedded resource. public static IEnumerable EnumerateLines(string filename) { return EnumerateLines(Assembly.GetCallingAssembly(), filename); } /// /// Enumerates the lines of text in the embedded resource that's /// embedded in the specified assembly. /// /// The filename of the embedded resource to enumerate. /// An IEnumerator that enumerates the specified embedded resource. public static IEnumerable EnumerateLines(Assembly targetAssembly, string filename) { foreach (Task nextLine in EnumerateLinesAsync(targetAssembly, filename)) yield return nextLine.Result; } /// /// Enumerates the lines of text in the resource that's embedded in the /// specified assembly asynchronously. /// Each successive call returns a task that, when complete, returns /// the next line of text stored in the embedded resource. /// /// The target assembly in which to look for the embedded resource. /// The filename of the embedded resource to enumerate. /// An IEnumerator that enumerates the specified embedded resource. public static IEnumerable> EnumerateLinesAsync(Assembly targetAssembly, string filename) { using (StreamReader resourceReader = new StreamReader(targetAssembly.GetManifestResourceStream(filename))) { while (!resourceReader.EndOfStream) yield return resourceReader.ReadLineAsync(); } } /// /// Enumerates the lines of text in the resource that's embedded in the /// calling assembly asynchronously. /// Each successive call returns a task that, when complete, returns /// the next line of text stored in the embedded resource. /// /// The filename of the embedded resource to enumerate. /// An IEnumerator that enumerates the specified embedded resource. public static IEnumerable> EnumerateLinesAsync(string filename) { return EnumerateLinesAsync(Assembly.GetCallingAssembly(), filename); } /// /// Gets all the lines of text in the specified embedded resource. /// You might find EnumerateLines(string filename) more useful depending on your situation. /// /// The filename to obtain the lines of text from. /// A list of lines in the specified embedded resource. public static List GetAllLines(string filename) { // Referencing the Result property will block until the async method completes return GetAllLinesAsync(filename).Result; } /// /// Gets all the lines of text in the resource that's embedded in the /// calling assembly asynchronously. /// /// The filename to obtain the lines of text from. /// A list of lines in the specified embedded resource. public static async Task> GetAllLinesAsync(string filename) { return await GetAllLinesAsync(Assembly.GetCallingAssembly(), filename); } /// /// Gets all the lines of text in the resource that's embedded in the /// specified assembly asynchronously. /// /// The filename to obtain the lines of text from. /// A list of lines in the specified embedded resource. public static async Task> GetAllLinesAsync(Assembly targetAssembly, string filename) { List result = new List(); foreach (Task nextLine in EnumerateLinesAsync(targetAssembly, filename)) result.Add(await nextLine); return result; } } }