Чтение из сборки со встроенными ресурсами - PullRequest
5 голосов
/ 03 сентября 2010

Я собрал сборку, содержащую один файл js. Я пометил файл как встроенный ресурс и добавил его в файл AssemblyInfo.

Я не могу ссылаться на Ассамблею с веб-сайта. Он находится в папке bin, но я не вижу ссылки на него.

Кажется, что в сборке нет хотя бы класса, я не могу на него ссылаться

Я бы включил файл js в свои страницы из сборки.

Как мне это сделать?

Спасибо

Ответы [ 3 ]

3 голосов
/ 03 сентября 2010

Я делаю то же самое в одном из моих проектов. У меня есть центральный класс ScriptManager, который на самом деле кэширует скрипты при их извлечении, но ядро ​​извлечения файла скрипта из встроенного ресурса выглядит следующим образом:

internal static class ScriptManager
{
    private static Dictionary<string, string> m_scriptCache = 
                                     new Dictionary<string, string>();

    public static string GetScript(string scriptName)
    {
        return GetScript(scriptName, true);
    }

    public static string GetScript(string scriptName, bool encloseInCdata)
    {
        StringBuilder script = new StringBuilder("\r\n");

        if (encloseInCdata)
        {
            script.Append("//<![CDATA[\r\n");

        }

        if (!m_scriptCache.ContainsKey(scriptName))
        {
            var asm = Assembly.GetExecutingAssembly();

            var stream = asm.GetManifestResourceStream(scriptName);

            if (stream == null)
            {
                var names = asm.GetManifestResourceNames();
                // NOTE: you passed in an invalid name.  
                // Use the above line to determine what tyhe name should be
                // most common is not setting the script file to be an embedded resource
                if (Debugger.IsAttached) Debugger.Break();

                return string.Empty;
            }

            using (var reader = new StreamReader(stream))
            {
                var text = reader.ReadToEnd();

                m_scriptCache.Add(scriptName, text);
            }
        }

        script.Append(m_scriptCache[scriptName]);

        if (encloseInCdata)
        {
            script.Append("//]]>\r\n");
        }

        return script.ToString();
    }
}

EDIT

Для большей ясности я опубликовал свой класс ScriptManager. Чтобы извлечь файл сценария, я просто называю его так:

var script = ScriptManager.GetScript("Fully.Qualified.Script.js");

Имя, которое вы передаете в нем, полное, чувствительное к регистру имя ресурса (обработчик исключений получает их список, вызывая GetManifestResourceNames()).

Это дает вам сценарий в виде строки - вы можете затем поместить его в файл, вставить его на страницу (что я и делаю) или что угодно.

0 голосов
/ 03 сентября 2010

Полностью рабочий пример (надеюсь):

namespace TestResources.Assembly
{
    public class ResourceLoader
    {
        public static void LoadResources()
        {
            Assembly myAssembly = Assembly.GetExecutingAssembly();

            Stream stream = myAssembly
                .GetManifestResourceStream("TestResources.Assembly.CheckAnswer.js");

            if (stream != null)
            {
                string directory = Path.GetDirectoryName("C:/WebApps/MyApp/Scripts/");

                using (Stream file = File.OpenWrite(directory + "MyScript.js"))
                {
                    CopyStream(stream, file);
                }

               stream.Dispose();
            }
        }

        private static void CopyStream(Stream input, Stream output)
        {
            byte[] buffer = new byte[8 * 1024];
            int len;

            while ((len = input.Read(buffer, 0, buffer.Length)) > 0)
            {
                output.Write(buffer, 0, len);
            }
        }
    }
}

Некоторые предостережения:

  • Измените "C: / WebApps / MyApp /" на то место, где находится ваше веб-приложение, возможно, напишите некоторый код для динамической обработки этого
  • Убедитесь, что в корневом каталоге вашего веб-приложения есть папка / Scripts
  • Я думаю, он перезапишет файл 'MyScript.js', если он уже существует, но на всякий случай вы можете добавить код для проверки этого файла и удалить его

Затем введите этот код в файл Global.asax:

protected void Application_Start()
{
    ResourceLoader.LoadResources();
}

Тогда путь к вашему веб-сайту будет /Scripts/MyScript.js, например:

<head>
    <!-- Rest of head (snip) -->
    <script type="text/javascript" src="/Scripts/MyScript.js"></script>
</head>
0 голосов
/ 03 сентября 2010
Assembly myAssembly = // Get your assembly somehow (see below)...
IList<string> resourceNames = myAssembly.GetManifestResourceNames();

Будет возвращен список всех имен ресурсов, которые были установлены как «Встроенный ресурс». Имя обычно является полностью определенным пространством имен, куда бы вы ни поместили этот файл JS. Поэтому, если ваш проект называется My.Project и вы храните файл MyScript.js в папке вашего проекта с именем Resources, полное имя будет My.Project.Resources.MyScript.js

Если вы хотите использовать этот JS-файл:

Stream stream = myAssembly.GetManifestResourceStream(myResourceName);

Где аргумент myResourceName может быть «My.Project.Resources.MyScript.js». Чтобы получить этот JS-файл в этом объекте Stream, вам нужно записать его в виде файла на жесткий диск и передать с веб-сайта в виде статического файла, что-то вроде этого:

Stream stream = executingAssembly.GetManifestResourceStream(imageResourcePath);
if (stream != null)
{
    string directory = Path.GetDirectoryName("C:/WebApps/MyApp/Scripts/");

    using (Stream file = File.OpenWrite(directory + "MyScript.js"))
    {
        CopyStream(stream, file);
    }

    stream.Dispose();
}

И код для метода CopyStream:

private static void CopyStream(Stream input, Stream output)
{
    byte[] buffer = new byte[8 * 1024];
    int len;
    while ((len = input.Read(buffer, 0, buffer.Length)) > 0)
    {
        output.Write(buffer, 0, len);
    }
}

Возможно, вы захотите вставить весь этот код в событие Application_Start в вашем Global.asax. Вы не хотите, чтобы он выполнялся для каждого запроса


Теперь получение ссылки на вашу сборку - это другое дело, есть много способов. Одним из способов является включение всего вышеупомянутого кода в соответствующую сборку, а затем убедитесь, что вы ссылаетесь на эту сборку из своего основного проекта WebApp в Visual Studio, а затем получаете ссылку на текущую исполняемую сборку следующим образом.

namespace My.Project
{
    public class ResourceLoader
    {
        public static void LoadResources()
        {
            Assembly myAssembly = Assembly.GetExecutingAssembly();

            // rest of code from above (snip)
        }
    }
}

Затем вызовите ResourceLoader.LoadResources () из вашего события Application_Start в вашем Global.asax.

Надеюсь, это поможет

...