-
Notifications
You must be signed in to change notification settings - Fork 0
Host Integration
RuleScript is designed to be embedded. The host owns engine configuration, runtime variables, Host Functions, imports, diagnostics, runtime events, and Host Trigger lifecycle.
var context = new RuntimeContext();
context.Set("Distance", 519);
context.Set("Name", "Mick");
engine.Execute("result = Name + \": \" + ToString(Distance);", context);
Console.WriteLine(context.Get<string>("result"));RuntimeContext stores shared host/script variables. Use global.name inside functions when a script must explicitly read or write the shared context.
var engine = new RuleScriptEngine();
engine.RegisterFunction("GetDistance", _ => 519);
engine.RegisterFunction("Alarm", args =>
{
Console.WriteLine(args[0]);
return null;
});Host Functions receive IReadOnlyList<object?> and return object?. Registering the same name replaces the previous registration.
engine.RegisterFunctionAsync("ReadAsync", async (args, cancellationToken) =>
{
return await service.ReadAsync(args[0]?.ToString(), cancellationToken);
});Async Host Functions require ExecuteAsync, ExecuteFileAsync, or a RuleScriptRuntime started with StartAsync.
engine.RegisterFunction(
"Add",
[
new RuleScriptParameterSymbol("left", RuleScriptValueType.Number),
new RuleScriptParameterSymbol("right", RuleScriptValueType.Number)
],
RuleScriptValueType.Number,
args => Convert.ToDouble(args[0]) + Convert.ToDouble(args[1]));Typed Host Functions validate argument count and types before invocation and validate the returned value afterward. Equivalent overloads exist for RegisterFunctionAsync.
Use RuleScriptHostFunctionOptions when registration needs typed metadata, thread safety, and documentation:
engine.RegisterFunction(
"FindPlayer",
args => FindPlayer(args[0]),
new RuleScriptHostFunctionOptions
{
Parameters = [new("id", RuleScriptValueType.Number)],
ReturnType = RuleScriptValueType.String,
ThreadSafe = true,
Documentation = "Finds a player by ID."
});Documentation appears in RegisteredFunctionSymbols, Analyze, completion metadata, hover metadata, and navigation metadata.
public sealed class SensorFunctions
{
[RuleScriptFunction(
Name = "LoadSensor",
ThreadSafe = true,
Documentation = "Loads a sensor reading by name.")]
public decimal Load(string name) => 519m;
[RuleScriptFunction(Name = "ReadSensor", ThreadSafe = true)]
public Task<decimal> ReadAsync(string name, CancellationToken cancellationToken)
=> sensor.ReadAsync(name, cancellationToken);
}
var count = engine.RegisterFunctions(new SensorFunctions());RegisterFunctions(object) registers public instance methods decorated with RuleScriptFunctionAttribute. A final CancellationToken parameter is injected by the engine and is not visible to the script.
Host Functions called from ordinary parallel task blocks must be explicitly marked thread-safe:
engine.RegisterFunction(
"LoadSensor",
args => sensorService.Load(args[0]?.ToString()),
threadSafe: true);Only mark a function thread-safe when concurrent calls are safe. The rule applies to ordinary parallel tasks; Host Trigger handlers are dispatched by the runtime queue.
v1.10.0 adds long-running Host Trigger runtime support.
var engine = new RuleScriptEngine
{
ExecutionTimeoutEnabled = false
};
var runtime = engine.CreateRuntime(script);
var running = runtime.StartAsync();
await runtime.TriggerAsync("LotArrived", ["LOT-001"]);
await runtime.StopAsync();
await running;Scripts expose handlers with @HostTrigger("Name") and include a trigger task dispatcher:
@HostTrigger("LotArrived")
function OnLotArrived(lotId: string) -> void:
Print(lotId);
return;
endfunction
parallel:
trigger task:
dispatch;
endtask
endparallel
Use CreateRuntimeFromFile when the script is part of a project. It follows the same file, extension, import, and working-directory behavior as ExecuteFile.
engine.RuntimeEventHandler = runtimeEvent =>
{
if (runtimeEvent.Kind == RuleScriptRuntimeEventKind.Print)
{
Console.WriteLine(runtimeEvent.Value);
}
return RuleScriptExecutionDirective.Continue;
};Use RuntimeEventHandlerAsync for asynchronous hosts and Host Trigger runtimes. Runtime events include current-line changes, Print, breakpoint hits, step pauses, and errors.
Implement IImportResolver to load scripts from virtual storage:
public interface IImportResolver
{
string GetFullPath(string path);
bool Exists(string path);
string ReadAllText(string path);
}ExecuteFile, ExecuteFileAsync, CreateRuntimeFromFile, imports, analysis, navigation, and debug sessions all use the configured resolver.