Как я могу узнать «путь» встроенного ресурса?

110

Я сохраняю PNG как встроенный ресурс в сборке. Из той же сборки у меня есть такой код:

Bitmap image = new Bitmap(typeof(MyClass), "Resources.file.png");

Файл с именем «file.png» хранится в папке «Ресурсы» (в Visual Studio) и помечен как встроенный ресурс.

Код не работает с исключением, говорящим:

Ресурс MyNamespace.Resources.file.png не может быть найден в классе MyNamespace.MyClass

У меня идентичный код (в другой сборке, загрузка другого ресурса), который работает. Так что я знаю, что техника правильная. Моя проблема в том, что я трачу много времени, пытаясь выяснить, каков правильный путь. Если бы я мог просто запросить (например, в отладчике) сборку, чтобы найти правильный путь, это избавило бы меня от множества головных болей.

Роб
источник

Ответы:

198

Это даст вам строковый массив всех ресурсов:

System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceNames();
Джон
источник
3
Привет, как я могу получить путь к папке ресурсов, чтобы назначить его корневым каталогом для моего встроенного HTTP-сервера?
lazzy_ms 02
45

Я ловлю себя на том, что каждый раз забываю, как это делать, поэтому просто оборачиваю два однострочника, которые мне нужны, в небольшой класс:

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();
    }
}
Дилан
источник
19

Я предполагаю, что ваш класс находится в другом пространстве имен. Канонический способ решить эту проблему - использовать класс ресурсов и строго типизированный ресурс:

ProjectNamespace.Properties.Resources.file

Используйте диспетчер ресурсов IDE для добавления ресурсов.

Конрад Рудольф
источник
Вы правы, мой класс находится в другом пространстве имен. Кажется, что папка Resources находится в пространстве имен, указанном в качестве пространства имен по умолчанию в конфигурации проекта, которое по разным причинам не является пространством имен, частью которого является этот класс. Я подозреваю, что вы правы и в том, что используете совершенно другой подход, но, поскольку мне нужно соответствовать устаревшему коду, это вне моего контроля.
Роб
7
Это захватывает ресурс, а не путь к файлу.
Учиха Итачи
3
@UchihaItachi Вот почему я предложил этот ответ явно как еще один (и, возможно, канонический) способ решения основной проблемы, а не дословный ответ на вопрос (на который уже есть ответ).
Конрад Рудольф
1
@UchihaItachi В этом вопросе также рассказывается о проблеме, с которой сталкивается спрашивающий, каков его подход и как он пытался. Хотя Рудольф прямо не отвечает на этот вопрос, он обращается к другому подходу к решению проблемы. В большинстве случаев такой подход более удобен, безопасен и распространен. Этот ответ полезен. Я просто не понимаю, почему вы должны пытаться закрыть ответы людей. Кнопки «Голосовать за» / «Голосовать против» существуют не просто так.
Нин
5

Я использую следующий метод для получения встроенных ресурсов:

    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")
мастер
источник
3

Имя ресурса - это пространство имен плюс пространство имен «псевдо» пути к файлу. «Псевдо» пространство имен создается структурой подпапок с использованием \ (обратной косой черты) вместо. (точки).

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, расположенный в папке resources \ xml в пространстве имен: my.namespace.

user3356450
источник
6
Также дефисы ('-') в папках заменяются символами подчеркивания ('_'). Могут быть и другие символы. Я хотел бы посмотреть, как это делает компилятор, чтобы мы могли использовать тот же метод.
Бойко Караджов