tags: - api - EverSharpRunner - reference - integration
EverSharpRunner API Reference¶
Complete C# API reference for integrating EverSharp into .NET applications.
Overview¶
EverSharpRunner is the primary class for executing EverSharp scripts from C#. It provides methods for running scripts, expressions, managing environments, and handling errors.
Class Definition¶
Constructor¶
EverSharpRunner(IEnumerable\<string>? libraries, Dictionary\<string, Callable>? extensions)¶
Creates a new EverSharpRunner instance.
Parameters:
libraries(optional): Collection of library scripts to execute on initializationextensions(optional): Dictionary of custom native functions to register
Example:
// Basic instantiation
var runner = new EverSharpRunner();
// With libraries
var libraries = new[] {
"PI = 3.14159;",
"function square(n) { return n * n; }"
};
var runner = new EverSharpRunner(libraries);
// With custom extensions
var extensions = new Dictionary<string, Callable>
{
["$MyFunction"] = new MyCustomFunction()
};
var runner = new EverSharpRunner(null, extensions);
Core Execution Methods¶
Run(string source)¶
Executes a complete EverSharp script containing statements and declarations.
Parameters:
source: EverSharp script code to execute
Returns: void
Example:
var runner = new EverSharpRunner();
string script = @"
x = 10;
y = 20;
result = x + y;
";
runner.Run(script);
// Check for errors
if (runner.HasErrors)
{
foreach (var error in runner.Errors)
{
Console.WriteLine($"Error: {error}");
}
}
Use Cases:
- Running multi-line scripts
- Executing function declarations
- Running initialization scripts
RunExpression(string source)¶
Evaluates a single EverSharp expression and returns its result.
Parameters:
source: EverSharp expression to evaluate
Returns: object? - The result of the expression, or null if error occurred
Example:
var runner = new EverSharpRunner();
// Evaluate arithmetic
var result = runner.RunExpression("10 + 5 * 2");
Console.WriteLine(result); // 20
// Evaluate with variables
runner.Run("x = 100;");
var doubled = runner.RunExpression("x * 2");
Console.WriteLine(doubled); // 200
// Call functions
runner.Run("function add(a, b) { return a + b; }");
var sum = runner.RunExpression("add(5, 3)");
Console.WriteLine(sum); // 8
Use Cases:
- Calculating single values
- Evaluating formulas
- Quick expression evaluation without statements
Environment Management¶
InitializeEnvironment(EverDictionary constants, EverDictionary variables)¶
Initializes the global environment with constants and variables from C#.
Parameters:
constants: Dictionary of constant values (read-only in EverSharp)variables: Dictionary of variable values (read-write in EverSharp)
Example:
using Elements.Libs.Extensions.EverDictionaries;
var runner = new EverSharpRunner();
// Create constants (read-only from EverSharp)
var constants = new EverDictionary
{
["TAX_RATE"] = 0.08m,
["MAX_AMOUNT"] = 10000m,
["COMPANY_NAME"] = "Acme Insurance"
};
// Create variables (read-write from EverSharp)
var variables = new EverDictionary
{
["policyNumber"] = "POL-12345",
["premium"] = 1200m,
["effectiveDate"] = DateTime.Parse("2024-01-01")
};
runner.InitializeEnvironment(constants, variables);
// Access in script
runner.Run(@"
taxAmount = premium * TAX_RATE;
totalAmount = premium + taxAmount;
");
// Get results back
var total = runner.GlobalVariables["totalAmount"];
Console.WriteLine($"Total: {total}"); // Total: 1296
SetExternalVariable(string name, object? value)¶
Sets or updates a single global variable from C#.
Parameters:
name: Variable namevalue: Variable value
Example:
var runner = new EverSharpRunner();
// Set individual variables
runner.SetExternalVariable("customerName", "John Smith");
runner.SetExternalVariable("age", 35);
runner.SetExternalVariable("premium", 1200m);
// Use in script
runner.Run(@"
if (age < 25) {
adjustedPremium = premium * 1.5;
} else {
adjustedPremium = premium;
}
");
// Get result
var adjusted = runner.GlobalVariables["adjustedPremium"];
Console.WriteLine($"Adjusted Premium: {adjusted}");
Properties¶
HasErrors (bool)¶
Indicates whether any errors occurred during the last execution.
Example:
runner.Run("x = 10 / 0;"); // Division by zero
if (runner.HasErrors)
{
Console.WriteLine("Execution failed");
}
Errors (IEnumerable\<string>)¶
Collection of error messages from the last execution.
Example:
runner.Run("invalid syntax here");
if (runner.HasErrors)
{
foreach (var error in runner.Errors)
{
Console.WriteLine($"Error: {error}");
}
}
GlobalVariables (EverDictionary)¶
Read-only dictionary of all global variables and their current values.
Example:
runner.Run(@"
x = 10;
y = 20;
result = x + y;
");
var x = runner.GlobalVariables["x"];
var y = runner.GlobalVariables["y"];
var result = runner.GlobalVariables["result"];
Console.WriteLine($"x={x}, y={y}, result={result}");
// Output: x=10, y=20, result=30
GlobalConstants (EverDictionary)¶
Read-only dictionary of all global constants.
Example:
var constants = new EverDictionary
{
["PI"] = 3.14159m,
["MAX_VALUE"] = 1000m
};
runner.InitializeEnvironment(constants, new EverDictionary());
// Constants are available
var pi = runner.GlobalConstants["PI"];
Console.WriteLine($"PI = {pi}"); // PI = 3.14159
Globals (EverDictionary)¶
Combined dictionary of all globals (constants + variables).
Example:
var constants = new EverDictionary { ["TAX_RATE"] = 0.08m };
var variables = new EverDictionary { ["amount"] = 1000m };
runner.InitializeEnvironment(constants, variables);
runner.Run("total = amount * (1 + TAX_RATE);");
// Access all globals
foreach (var kvp in runner.Globals)
{
Console.WriteLine($"{kvp.Key} = {kvp.Value}");
}
// Output:
// TAX_RATE = 0.08
// amount = 1000
// total = 1080
StandardOutput (string)¶
Accumulated output from $Log() calls in the script.
Example:
runner.Run(@"
$Log('Starting calculation');
result = 10 + 5;
$Log('Result: ' + $ToString(result));
");
Console.WriteLine(runner.StandardOutput);
// Output:
// Starting calculation
// Result: 15
Practical Examples¶
Example 1: Simple Calculator¶
public decimal Calculate(string expression)
{
var runner = new EverSharpRunner();
var result = runner.RunExpression(expression);
if (runner.HasErrors)
{
throw new Exception($"Calculation error: {string.Join(", ", runner.Errors)}");
}
return Convert.ToDecimal(result);
}
// Usage
var result = Calculate("(100 + 50) * 0.08");
Console.WriteLine(result); // 12
Example 2: Insurance Premium Calculator¶
public class PremiumCalculator
{
private readonly EverSharpRunner runner;
public PremiumCalculator()
{
runner = new EverSharpRunner();
// Load business rules
string rules = @"
function calculatePremium(baseAmount, age, riskFactor) {
premium = baseAmount;
if (age < 25) {
premium = premium * 1.5;
} else if (age > 65) {
premium = premium * 1.3;
}
premium = premium * riskFactor;
return premium;
}
";
runner.Run(rules);
}
public decimal CalculatePremium(decimal baseAmount, int age, decimal riskFactor)
{
runner.SetExternalVariable("baseAmount", baseAmount);
runner.SetExternalVariable("age", age);
runner.SetExternalVariable("riskFactor", riskFactor);
var result = runner.RunExpression("calculatePremium(baseAmount, age, riskFactor)");
if (runner.HasErrors)
{
throw new Exception($"Error: {string.Join(", ", runner.Errors)}");
}
return Convert.ToDecimal(result);
}
}
// Usage
var calculator = new PremiumCalculator();
var premium = calculator.CalculatePremium(1000m, 28, 1.2m);
Console.WriteLine($"Premium: ${premium}"); // Premium: $1440
Example 3: Dynamic Business Rules¶
public class RuleEngine
{
private readonly EverSharpRunner runner;
public RuleEngine(string rulesScript)
{
runner = new EverSharpRunner();
runner.Run(rulesScript);
if (runner.HasErrors)
{
throw new Exception($"Failed to load rules: {string.Join(", ", runner.Errors)}");
}
}
public bool EvaluateRule(string ruleName, Dictionary<string, object> context)
{
// Set context variables
foreach (var kvp in context)
{
runner.SetExternalVariable(kvp.Key, kvp.Value);
}
// Evaluate rule
var result = runner.RunExpression($"{ruleName}()");
if (runner.HasErrors)
{
throw new Exception($"Rule evaluation failed: {string.Join(", ", runner.Errors)}");
}
return Convert.ToBoolean(result);
}
}
// Usage
string rules = @"
function isEligibleForDiscount() {
return age >= 25 && yearsWithCompany >= 5 && claimCount == 0;
}
function isHighRisk() {
return age < 25 || claimCount > 2;
}
";
var engine = new RuleEngine(rules);
var context = new Dictionary<string, object>
{
["age"] = 30,
["yearsWithCompany"] = 6,
["claimCount"] = 0
};
bool eligible = engine.EvaluateRule("isEligibleForDiscount", context);
Console.WriteLine($"Eligible for discount: {eligible}"); // true
bool highRisk = engine.EvaluateRule("isHighRisk", context);
Console.WriteLine($"High risk: {highRisk}"); // false
Example 4: Multi-Step Calculation¶
public class PolicyCalculator
{
public PolicyResult CalculatePolicy(PolicyInput input)
{
var runner = new EverSharpRunner();
// Initialize with input data
var variables = new EverDictionary
{
["coverageAmount"] = input.CoverageAmount,
["age"] = input.Age,
["hasDiscount"] = input.HasDiscount,
["baseRate"] = input.BaseRate
};
runner.InitializeEnvironment(new EverDictionary(), variables);
// Execute multi-step calculation
string script = @"
// Step 1: Calculate base premium
basePremium = coverageAmount * baseRate / 1000;
// Step 2: Apply age factor
if (age < 30) {
ageFactor = 1.2;
} else if (age < 50) {
ageFactor = 1.0;
} else {
ageFactor = 1.3;
}
adjustedPremium = basePremium * ageFactor;
// Step 3: Apply discount
if (hasDiscount) {
discount = adjustedPremium * 0.10;
finalPremium = adjustedPremium - discount;
} else {
discount = 0;
finalPremium = adjustedPremium;
}
";
runner.Run(script);
if (runner.HasErrors)
{
throw new Exception($"Calculation failed: {string.Join(", ", runner.Errors)}");
}
// Extract results
return new PolicyResult
{
BasePremium = Convert.ToDecimal(runner.GlobalVariables["basePremium"]),
AgeFactor = Convert.ToDecimal(runner.GlobalVariables["ageFactor"]),
AdjustedPremium = Convert.ToDecimal(runner.GlobalVariables["adjustedPremium"]),
Discount = Convert.ToDecimal(runner.GlobalVariables["discount"]),
FinalPremium = Convert.ToDecimal(runner.GlobalVariables["finalPremium"])
};
}
}
public class PolicyInput
{
public decimal CoverageAmount { get; set; }
public int Age { get; set; }
public bool HasDiscount { get; set; }
public decimal BaseRate { get; set; }
}
public class PolicyResult
{
public decimal BasePremium { get; set; }
public decimal AgeFactor { get; set; }
public decimal AdjustedPremium { get; set; }
public decimal Discount { get; set; }
public decimal FinalPremium { get; set; }
}
Example 5: Script Validation¶
public class ScriptValidator
{
public ValidationResult Validate(string script)
{
var runner = new EverSharpRunner();
// Try to run the script
runner.Run(script);
if (runner.HasErrors)
{
return new ValidationResult
{
IsValid = false,
Errors = runner.Errors.ToList()
};
}
return new ValidationResult
{
IsValid = true,
Errors = new List<string>()
};
}
public ValidationResult ValidateExpression(string expression)
{
var runner = new EverSharpRunner();
var result = runner.RunExpression(expression);
if (runner.HasErrors)
{
return new ValidationResult
{
IsValid = false,
Errors = runner.Errors.ToList()
};
}
return new ValidationResult
{
IsValid = true,
Errors = new List<string>()
};
}
}
public class ValidationResult
{
public bool IsValid { get; set; }
public List<string> Errors { get; set; }
}
// Usage
var validator = new ScriptValidator();
var result1 = validator.ValidateExpression("10 + 5 * 2");
Console.WriteLine($"Valid: {result1.IsValid}"); // true
var result2 = validator.ValidateExpression("10 + * 5");
Console.WriteLine($"Valid: {result2.IsValid}"); // false
foreach (var error in result2.Errors)
{
Console.WriteLine($" Error: {error}");
}
Error Handling¶
Common Error Scenarios¶
var runner = new EverSharpRunner();
// Syntax error
runner.Run("x = 10 +");
if (runner.HasErrors)
{
Console.WriteLine("Syntax error detected");
}
// Runtime error
runner.Run("result = undefinedVariable;");
if (runner.HasErrors)
{
Console.WriteLine("Runtime error: undefined variable");
}
// Type error
runner.Run("result = 'text' + 5;"); // String concatenation works
runner.Run("result = 'text' * 5;"); // Type error
if (runner.HasErrors)
{
Console.WriteLine("Type error: invalid operation");
}
Best Practices¶
- Always check HasErrors after execution:
runner.Run(script);
if (runner.HasErrors)
{
// Handle errors
LogErrors(runner.Errors);
return;
}
// Continue with success logic
- Clear errors between runs (automatic):
// Errors are automatically cleared on each Run/RunExpression call
runner.Run("x = 10;"); // Success
runner.Run("invalid"); // Error - previous errors are cleared
- Use appropriate method for task:
// Use Run() for scripts with statements
runner.Run("x = 10; y = 20;");
// Use RunExpression() for single expressions
var result = runner.RunExpression("x + y");
Thread Safety¶
EverSharpRunner is not thread-safe. Each thread should have its own instance:
// Wrong - sharing instance across threads
var sharedRunner = new EverSharpRunner();
Parallel.For(0, 10, i =>
{
sharedRunner.Run($"x = {i};"); // Race condition!
});
// Correct - instance per thread
Parallel.For(0, 10, i =>
{
var runner = new EverSharpRunner();
runner.Run($"x = {i};");
});
Performance Considerations¶
- Reuse instances when possible:
// Good - reuse runner for multiple calculations
var runner = new EverSharpRunner();
for (int i = 0; i < 1000; i++)
{
runner.SetExternalVariable("value", i);
var result = runner.RunExpression("value * 2");
}
// Less efficient - creating new instance each time
for (int i = 0; i < 1000; i++)
{
var runner = new EverSharpRunner(); // New instance overhead
var result = runner.RunExpression($"{i} * 2");
}
- Pre-compile scripts:
// Load and compile rules once
var runner = new EverSharpRunner();
runner.Run(complexRulesScript); // Parse once
// Execute many times with different data
for (int i = 0; i < 1000; i++)
{
runner.SetExternalVariable("input", i);
var result = runner.RunExpression("processInput(input)");
}
See Also¶
- Environment Setup - Data passing between C# and EverSharp
- Extension Functions - Creating custom native functions
- Using EverSharpRunner - Getting started guide