Песочница

Песочница скрипта

Песочница это штука, в которой запускаются ваши скрипты. Она предоставляет объект host/globals с базовыми методами и свойствами. В Script.csx они доступны напрямую; обычные C# классы их не наследуют и должны получать зависимости явно.

Зачем она нужна?

Хранит в себе состояние между запусками

Когда вы создаете какое-то свойство или службу, отрисовываете картинку на экране или распознаете текст, то во избежание многократного создания одного и того же, песочница сохраняет и переиспользует данные от предыдущих запусков. Это увеличивает производительность и делает написание скриптов более простым

Подчищает за скриптом мусор

Ресурсы одного запуска можно привязать к ExecutionAnchors: они освобождаются при выходе из Run. Сама песочница и её Anchors могут жить дольше и переиспользоваться. Созданные вами подписки и другие ресурсы требуют явного управления временем жизни; не каждый результат GetService автоматически освобождается за вас. e0219e2e257a9878d5b6b2323dcb9c37.jpg

Предоставляет набор базового функционала

Чтобы было проще жить, в абсолютно любом скрипте по умолчанию присутствует набор неких базовых сервисов - возможность писать логи, возможность работы с файлами программы и т.п. Однако, во избежание накопления лишнего веса, этот функционал очень и очень ограничен. Предполагается, что пользователь пользуется методом GetService<> чтобы добавить скрипту любые нужные ему возможности. Об этом чуть ниже

Что там по коду

Давайте рассмотрим методы и свойства, которые есть у абсолютно любого скрипта

Логгирование

IFluentLog Log { get; }

Почти любому скрипту на одном из этапов жизни нужно давать какую-то обратную связь - текущие значения переменных, отладочные сообщения и т.п. Log отвечает именно за это. С его помощью можно писать сообщения как в файлы логов программы, так и в окошко Event Log. У каждой строчки лога есть один из уровней: Debug, Info, Warn, Error Чем выше уровень - тем важнее сообщение, Error самые важные. В Event Log вы можете регулировать от какого уровня показывать сообщения. По умолчанию от Info и выше

csharp
Log.Info("Hello!");
Log.Debug("Hello from debug level!");

Любителям поспать

csharp
void Sleep(TimeSpan delay);
void Sleep(int delayMs)

Этот метод приостанавливает выполнение скрипта на указанное время. Он использует текущий cancellationToken. Это синхронная пауза; для асинхронного ожидания используйте await Task.Delay(..., token).

csharp
Sleep(2000); //приостанавливаем скрипт на 2 секунды
Sleep(TimeSpan.FromMilliseconds(100)); //приостанавливаем на 100 миллисекунд

Если по какой-то причине программа попросит скрипт остановиться (к примеру, ауру со скриптом выгрузили), то Sleep прервется заранее и скрипт будет остановлен

Dependency Injection

T GetService<T>()

Самый могучий метод в песочнице. Это связь вашего скрипта с внешним миром и возможность получить доступ к разным частям функционала программы. Используя GetService вы можете запросить у программы ниточки, дергая за которые будете получать тот или иной эффект. Вместо тысячи слов:

Например, передадим логгер обычному классу. В Script.csx:

csharp
var reporter = new Reporter(Log);
reporter.Report(2 + 3);

В отдельном Reporter.cs:

csharp
using PoeShared.Logging;

public sealed class Reporter
{
    private readonly IFluentLog log;
    public Reporter(IFluentLog log) => this.log = log;
    public void Report(int value) => log.Info($"Result: {value}");
}

В Event Log появится Result: 5. Для получения зарегистрированной службы используйте её точный интерфейс и namespace; наличие типа в SDK ещё не гарантирует регистрацию. Свои службы можно добавить через Script Container Extensions.

Выполнить работу с отменой одного запуска

Код для Script.csx:

csharp
using System.Threading.Tasks;

var runToken = cancellationToken;
for (var step = 1; step <= 3; step++)
{
    runToken.ThrowIfCancellationRequested();
    Log.Info($"Step {step}");
    await Task.Delay(500, runToken);
}

Скрипт пишет три сообщения с паузами. Если host отменит запуск, ожидание прервётся отменой. cancellationToken и ExecutionAnchors назначаются для каждого Run, а после него сбрасываются. Захватите токен и передайте его в выполняемую работу; не храните его как постоянный токен всей песочницы и не оставляйте неотслеживаемые фоновые задачи после выхода.

Состояние объекта скрипта может сохраняться при повторных запусках с той же версией проекта. Изменение зависимой версии проекта пересоздаёт контекст; это не долговременное хранилище. Для обмена данными и настроек смотрите переменные, для ресурсов — управление временем жизни.