Embedded Resources — это механизм в скриптах, который позволяет «нести с собой» любые файлы прямо рядом со скриптом: изображения, видео, ML-модели, исполняемые файлы и даже DLL.
Изображения можно использовать в вашем кастомном UI, видео — для обучающих материалов, а DLL — для дополнительного кода, который по каким-то причинам неудобно поставлять как пакет NuGet.
Обратите внимание: если библиотека уже есть на NuGet, гораздо надежнее подключать её через #r "nuget:" и ссылаться на пакет, а не на «сырую» DLL.
Щелкните правой кнопкой мыши по дереву файлов скрипта (его показывает кнопка Show Files) → Add Existing File...

Либо воспользуйтесь кнопкой New.
После добавления файл появится в списке, и его можно будет выбрать.

Чтобы удалить ресурс, просто удалите файл из списка.
Когда скрипт запускается, выбранные вами файлы загружаются автоматически, и скрипт может их использовать.
Этот способ позволяет прочитать содержимое файла как текст или как массив байтов. Что делать с этими байтами дальше — решаете вы.
var fontData = GetService<IScriptFileProvider>().ReadAllBytes("Roboto-Regular.ttf");
Если вы строите UI через Blazor, файлы можно использовать напрямую. Например, если вы добавили в скрипт Image 12.jpg, то для отображения достаточно написать:
<img src="Image 12.jpg" />
Точно так же можно показывать видео, загружать текст, стили и всё остальное.
По аналогии с пакетами NuGet, вы можете положить нужную DLL прямо в скрипт и при этом сохранить автодополнение, определение типов и прочие удобства.
Для этого нужно:
MyDll.dllScript.csx написать#r "assemblyPath: MyDll.dll"
Готово. При компиляции скрипта EyeAuras найдет подходящую DLL среди ресурсов проекта и использует её. А при запуске скрипта загрузит её из ресурсов. Никаких отдельных файлов рядом держать не нужно.
EyeAuras умеет экспортировать скрипт как полноценный C# .sln, который потом можно открыть в JetBrains Rider или Visual Studio.
Embedded resources (файлы) тоже экспортируются и помечаются как Embedded Resource.
Например, для Image 12.jpg произойдет следующее: во-первых, сам файл будет экспортирован в целевую папку, а во-вторых, в экспортированном файле проекта появится:
<ItemGroup>
<EmbeddedResource Include="Image 12.jpg" />
<None Remove="Image 12.jpg" />
</ItemGroup>
Это говорит C#-компилятору включить Image 12.jpg как embedded resource внутрь итоговой DLL.
При обратном импорте .sln в EyeAuras читаются элементы Embedded Resource, и вы увидите их как файлы в списке.
В Visual Studio/Rider это соответствует Build Action = EmbeddedResource. Если вы открыли экспортированный проект, можно:
.csproj указывать <EmbeddedResource Include="..."/> для каждого ресурса<None Remove="..."/>, чтобы файл не копировался в выходную папку как обычный контентПри импорте обратно EyeAuras просканирует .csproj, найдет все EmbeddedResource-элементы и покажет их в списке файлов скрипта. Имена и относительные пути сохраняются — это важно для корректного доступа из кода и Blazor.

При сборке скриптов EyeAuras старается максимально следовать логике официального компилятора: добавленные вами файлы включаются в итоговую DLL как Embedded Resources и доступны через Assembly.GetManifestResourceNames и Assembly.GetManifestResourceStream.
Кратко о .NET-методах:
Assembly.GetManifestResourceNames() — возвращает полный список имен ресурсов, например "DefaultNamespace.folder.file.ext"Assembly.GetManifestResourceStream(fullName) — открывает поток для чтения ресурса по его ПОЛНОМУ имениПример «в лоб» (обычно это не нужно — удобнее использовать IScriptFileProvider):
var asm = typeof(Script).Assembly; // your script’s assembly
foreach (var name in asm.GetManifestResourceNames())
{
Log.Info($"Resource: {name}");
}
using var stream = asm.GetManifestResourceStream("MyScript.Images.logo.png");
using var ms = new MemoryStream();
stream.CopyTo(ms);
var bytes = ms.ToArray();
В EyeAuras удобнее использовать IScriptFileProvider, потому что он сам сопоставляет пути и находит нужный ресурс.
У C# Embedded Resources есть одна особенность: когда ресурсы попадают в DLL, их относительный путь «сворачивается» и превращается в namespace.folder.filename.
Как формируется полное имя ресурса во время сборки:
DefaultNamespace проекта (если он не задан — имя проекта)FullName = DefaultNamespace + "." + relative/path/with/dotsMyScript и файл Images/logo.png → ресурс: MyScript.Images.logo.pngКак искать ресурс в EyeAuras:
"logo.png" — провайдер заменит слеши на точки и будет искать по суффиксу без учета регистра"Images/logo.png" или "Images.logo.png" — это надежнее"MyScript.Images.logo.png" — точное совпадение с учетом регистра'/', '\\' и '.' в запросе взаимозаменяемыВажно про совпадения и регистр:
EndsWith, без учета регистраa/logo.png и b/logo.png), короткий запрос "logo.png" вернет первое совпадение. Чтобы избежать путаницы, указывайте подпапку или полное имя.Примеры запросов, которые сработают для Images/logo.png:
"logo.png""Images/logo.png""Images.logo.png""MyScript.Images.logo.png"EyeAuras старается упростить жизнь пользователю и поддерживает как полные имена (с точками), так и относительные (без namespace). Можно также использовать привычные пути вроде folder/Image 12.jpg вместо folder.Image 12.jpg.
var files = GetService<IScriptFileProvider>();
var json = files.ReadAllText("config.json");
var cfg = JsonConvert.DeserializeObject<MyConfig>(json);
var files = GetService<IScriptFileProvider>();
var model = files.ReadAllBytes("models/my_model.onnx");
// pass the bytes into your ML library
var files = GetService<IScriptFileProvider>();
var file = files.GetFileInfo("video/tutorial.mp4");
using var stream = file.CreateReadStream();
// read in chunks without holding everything in memory
<img src="Images/logo.png" />
На этапе компиляции
Script.csx добавьте директиву:#r "assemblyPath: MyLib.dll"
MyLib.dll в ресурсах и добавит его как ссылку. Это даст автодополнение, определение типов и успешную компиляцию.Во время выполнения
AssemblyLoadContext.Resolving и пытается загрузить сборку из embedded resources.Полезный пример:
#r "assemblyPath: Newtonsoft.Json.dll"
using Newtonsoft.Json;
Log.Info(JsonConvert.SerializeObject(new { Hello = "World" }));
var asm = typeof(Script).Assembly;
foreach (var name in asm.GetManifestResourceNames())
{
Log.Info($"Resource: {name}");
}
IFileProvider):var files = GetService<IScriptFileProvider>();
foreach (var fi in files.GetDirectoryContents("/"))
{
Log.Info($"Found: {fi.Name} ({fi.Length} b)");
}
ScriptEmbeddedResourceFileProvider:var files = GetService<IScriptFileProvider>() as ScriptEmbeddedResourceFileProvider;
var names = files?.GetManifestNames() ?? Array.Empty<string>();
Log.Info(string.Join("\n", names));
Файл не находится
"logo.png" → "Images/logo.png"Дубликаты имен
a/logo.png и b/logo.png), короткий запрос "logo.png" может указать не на тот файл. Уточняйте путь через подпапку.Большие файлы
CreateReadStream() — не держите всё целиком в памятиЯ изменил файл, но не вижу обновлений
DLL не загружается
#r "assemblyPath: ..." указывает на правильный файл.Точки или слеши в путях?
"Images/logo.png", "Images.logo.png" — провайдер нормализует путь в точки и ищет по суффиксу.