Как я могу определить "путь” к встроенному ресурсу?
Вопрос
Я сохраняю PNG в качестве встроенного ресурса в сборке.Из той же сборки у меня есть некоторый код, подобный этому:
Bitmap image = new Bitmap(typeof(MyClass), "Resources.file.png");
Файл с именем "file.png" хранится в папке "Ресурсы" (в Visual Studio) и помечен как встроенный ресурс.
Код завершается ошибкой с исключением, гласящим:
Ресурс MyNamespace.Ресурсы.file.png не могут быть найдены в классе MyNamespace.MyClass
У меня есть идентичный код (в другой сборке, загружающий другой ресурс), который работает.Так что я знаю, что эта техника надежна.Моя проблема в том, что в конечном итоге я трачу много времени, пытаясь выяснить, каков правильный путь.Если бы я мог просто запросить (например.в отладчике) сборке, чтобы найти правильный путь, что избавило бы меня от массы головной боли.
Решение
Это даст вам строковый массив всех ресурсов:
System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceNames();
Другие советы
Я ловлю себя на том, что забываю, как это делать, каждый раз, поэтому я просто помещаю две однострочные строки, которые мне нужны, в небольшой урок:
public class Utility
{
/// <summary>
/// Takes the full name of a resource and loads it in to a stream.
/// </summary>
/// <param name="resourceName">Assuming an embedded resource is a file
/// called info.png and is located in a folder called Resources, it
/// will be compiled in to the assembly with this fully qualified
/// name: Full.Assembly.Name.Resources.info.png. That is the string
/// that you should pass to this method.</param>
/// <returns></returns>
public static Stream GetEmbeddedResourceStream(string resourceName)
{
return Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName);
}
/// <summary>
/// Get the list of all emdedded resources in the assembly.
/// </summary>
/// <returns>An array of fully qualified resource names</returns>
public static string[] GetEmbeddedResourceNames()
{
return Assembly.GetExecutingAssembly().GetManifestResourceNames();
}
}
Я предполагаю, что ваш класс находится в другом пространстве имен.Каноническим способом решения этой проблемы было бы использование класса resources и строго типизированного ресурса:
ProjectNamespace.Properties.Resources.file
Используйте диспетчер ресурсов IDE для добавления ресурсов.
Я использую следующий метод для захвата встроенных ресурсов:
protected static Stream GetResourceStream(string resourcePath)
{
Assembly assembly = Assembly.GetExecutingAssembly();
List<string> resourceNames = new List<string>(assembly.GetManifestResourceNames());
resourcePath = resourcePath.Replace(@"/", ".");
resourcePath = resourceNames.FirstOrDefault(r => r.Contains(resourcePath));
if (resourcePath == null)
throw new FileNotFoundException("Resource not found");
return assembly.GetManifestResourceStream(resourcePath);
}
Затем я вызываю это с помощью пути в проекте:
GetResourceStream(@"DirectoryPathInLibrary/Filename")
Имя ресурса - это пространство имен плюс пространство "псевдо" имен пути к файлу.Пространство "псевдо" имен создается структурой вложенных папок с использованием \ (обратной косой черты) вместо .(многоточие).
public static Stream GetResourceFileStream(String nameSpace, String filePath)
{
String pseduoName = filePath.Replace('\\', '.');
Assembly assembly = Assembly.GetExecutingAssembly();
return assembly.GetManifestResourceStream(nameSpace + "." + pseduoName);
}
Следующий вызов:
GetResourceFileStream("my.namespace", "resources\\xml\\my.xml")
вернет поток my.xml, расположенный в папке-structure resources\xml в пространстве имен:мое.пространствоимен.