Не удается найти файл .XSL, встроенный в DLL проекта - PullRequest
0 голосов
/ 16 мая 2019

Быстрый вопрос, который разрушил мое утро и сводит меня с ума.

У меня есть небольшой проект, который включает в себя DLL из другого проекта. В DLL встроен XSL-файл, который я хочу извлечь и применить к элементу управления веб-браузера.

У меня нет проблем с извлечением / доступом к встроенным ресурсам в основном EXE-файле, но я не могу найти способ доступа к ним в DLL!?

Я пробовал:

  • "SolutionName.DllName.Resource.xsl"
  • "ExeName.DllName.Resource.xsl"
  • "ProjectNamespace.DllNamespace.Resource.xsl"

... и почти каждая их перестановка, но она никогда не сможет ее найти.

У меня нет ссылки на точечную нотацию в C # для использования с nameof(), и я не могу найти какую-либо очевидную ссылку / доступ к ней с помощью:

System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceNames();

Итак, каков правильный метод именования (или другой метод?) Для извлечения этого файла?

В случае, если это поможет, вот некоторые дополнительные детали:

Название проекта: DataBuilder
Пространство имен проекта: DataBuilder
Имя DLL: CobCommon
Пространства имен DLL: CobCommon, CobCommon.Classes, CobCommon.Classes.Data, CobCommon.Winforms, CobCommon.WinForms.Controls
Имя ресурса XSL: XmlFormating.xsl

Указанная операция с файлом ресурсов называется «Встроенный ресурс» и находится в «корневой» области проекта DLL.

Доступ к global:: дает мне CobCommon и DataBuilder среди доступных вариантов, но CobCommon не имеет ни .Properties, ни * Опция 1064 * и DataBuilder с .Properties.Resources дают "Культура" в качестве единственной ссылки.

XSL-файл - это , указанный на вкладке «Свойства | Ресурсы | Файлы» проекта DLL.

Чего мне не хватает?

Ответы [ 2 ]

2 голосов
/ 16 мая 2019

Использование GetExecutingAssembly(), вероятно, всегда будет означать вашу сборку.Вместо этого создайте экземпляр некоторого безобидного ((надеюсь)) простого объекта, объявленного во внешней библиотеке DLL, а затем используйте объект этого экземпляра ...

<object-from-DLL>.GetType().Assembly.GetManifestResourceStream("what.youre.looking.for") 

, чтобы получить дескриптор потока для встроенного объекта.

0 голосов
/ 17 мая 2019

Таким образом, мне, наконец, удалось собрать универсальную функцию для извлечения любого текстового кодированного встроенного ресурса из любой сборки проекта (и это работает, как задумано в моем проекте):

Сначала я расширил класс Assembly, чтобы упростить захват только соответствующей ведущей части Assembly.FullName, которую нам нужно использовать для поиска запрошенного ресурса:

/// <summary>Adds a function to dereference just the base name portion of an Assembly from the FullName.</summary>
/// <returns>The extracted base name if able, otherwise just the FullName.</returns>
public static string ExtractName(this Assembly root)
{
    string pattern = @"^(?<assy>(?:[a-zA-Z\d]+[.]?)+)(?>,).*$", work = root.FullName;
    MatchCollection matches = Regex.Matches(work, pattern, RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture);
    if (matches.Count > 0) return matches[0].Groups["assy"].Value;

    if (work.IndexOf(",") > 3) return work.Substring(0, work.IndexOf(','));

    return root.FullName;
}

Затем я написал эту функциюнайти указанную сборку + файл встроенного ресурса и вернуть его содержимое в виде строки, если найдено:

/// <summary>Searches all loaded assemblies in a project for the specified embedded resource text file.</summary>
/// <returns>If the specified resource is found, its contents as a string, otherwise throws a DllNotFoundException.</returns>
/// <exception cref="DllNotFoundException"></exception>
public static string FetchAssemblyResourceFile(string name)
{
    Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();

    int i = -1; while ((++i < assemblies.Length) && !Regex.IsMatch(name, "^(" + assemblies[i].ExtractName() + ")", RegexOptions.IgnoreCase)) ;
    if (i < assemblies.Length)
    {
        try {
            using (System.IO.Stream stream = assemblies[i].GetManifestResourceStream(name))
            using (System.IO.StreamReader reader = new System.IO.StreamReader(stream))
                return reader.ReadToEnd();
        }
        catch (Exception innerExc)
        {
            Exception result = new Exception("The requested resource (\"" + name + "\") was not found.");
            result.InnerException = innerExc;
            throw result;
        }
    }
    throw new DllNotFoundException("The requested assembly resource (\"" + name + "\") could not be found.");
}
...