AOT Compatibility
RoslynRules supports AOT deployment via pre-compiled snapshots. Rules cannot be compiled at runtime in AOT — they must be compiled beforehand in a JIT environment.
RoslynRules Role: JIT vs AOT
| Capability | JIT Mode | AOT Mode |
|---|---|---|
| Load rules from JSON/EF | ✅ Yes | ✅ Yes |
Workflow.Validate() | ✅ Yes | ✅ Yes |
Workflow.GetExecutionOrder() | ✅ Yes | ✅ Yes |
Rule.Compile() (from string) | ✅ Yes | ❌ Not supported |
Rule.Execute() without snapshot | ✅ Yes | ❌ Throws error |
Rule.Execute() with snapshot | ✅ Yes | ✅ Yes |
| Create snapshots | ✅ Yes | ❌ Not supported |
| Load snapshots | ✅ Yes | ✅ Yes |
Key principle:
- JIT is the compilation environment
- AOT is the execution environment
Why AOT Cannot Compile
AOT removes the JIT compiler entirely. RoslynRules’ Compile() method requires:
CSharpCompilation.Emit()→ generates ILAssemblyLoadContext.LoadFromStream()→ loads dynamic assemblyMethodInfo.CreateDelegate()→ reflection on dynamic method
All three require a JIT compiler. AOT has none.
Deployment Architecture
Recommended: Two-Stage Deployment
[Rule Authoring] [Production Runtime]
│ │
▼ ▼
┌──────────┐ ┌──────────────┐
│ JSON/EF │──Compile()──→│ Snapshot │
│ Rules │ (JIT) │ Files │
└──────────┘ └──────────────┘
│ │
│ │ LoadSnapshot()
│ ▼
│ ┌──────────┐
│ │ AOT App │
│ │ Execute()│
│ └──────────┘
JIT Admin/Authoring Tool:
- Loads rules from JSON/EF
- Compiles with
ExpressionCompiler - Saves snapshots to disk/storage
- Can modify and recompile rules
AOT Production App:
- Loads rules from JSON/EF (for metadata)
- Loads pre-compiled snapshots
- Executes without compilation
Alternative: Self-Contained Single-File (Not AOT)
If you need dynamic compilation in production, do not use AOT. Use:
<!-- .csproj -->
<PublishAot>false</PublishAot>
<SelfContained>true</SelfContained>
<PublishSingleFile>true</PublishSingleFile>
This gives you:
- Single .exe file
- No runtime install needed
- Full dynamic compilation support
- Larger binary (~15-30MB vs ~5MB for AOT)
Snapshot API (Proposed)
// JIT: Compile and save
var workflow = JsonRuleLoader.LoadWorkflowFromFile("rules.json");
workflow.Compile(parameters);
foreach (var rule in workflow.Rules)
{
var snapshot = rule.ToSnapshot();
File.WriteAllBytes($"snapshots/{rule.Id}.snap", snapshot);
}
// AOT: Load and execute
var workflow = JsonRuleLoader.LoadWorkflowFromFile("rules.json");
foreach (var rule in workflow.Rules)
{
var snapshot = File.ReadAllBytes($"snapshots/{rule.Id}.snap");
rule.LoadSnapshot(snapshot);
}
var results = workflow.Execute(parameters);
Runtime Detection
RoslynRules detects AOT at runtime and throws clear errors:
if (!RuntimeFeature.IsDynamicCodeSupported)
{
throw new PlatformNotSupportedException(
"JIT compilation is not available in AOT mode. " +
"Use pre-compiled snapshots or run in JIT mode.");
}
Your app can also detect mode:
bool isAot = !RuntimeFeature.IsDynamicCodeSupported;
if (isAot)
{
workflow.LoadSnapshots("snapshots/");
}
else
{
workflow.Compile(parameters);
workflow.SaveSnapshots("snapshots/");
}
AOT-Safe APIs (No Compilation Needed)
These work in AOT without snapshots:
Workflow/Rulemodel creationWorkflow.Validate()— syntax validationWorkflow.GetExecutionOrder()— dependency resolutionRuleResultcreation and inspectionRuleContextresult storageGraphAlgorithms.TopologicalSort()
These require snapshots in AOT:
Rule.Execute()Workflow.Execute()Rule.Compile()ExpressionCompiler
CI Integration
The .github/workflows/aot.yml workflow validates AOT-safe APIs compile without linker errors:
dotnet test RoslynRules.Tests --filter "FullyQualifiedName~AotCompatibilityTests"
This runs 8 tests covering model creation, validation, RuleResult, RuleContext, and execution order — all without runtime compilation.
Known Limitations
System.Linq.Expressionsis not AOT-friendly; RoslynRules avoids itAssembly.LoadFromandReflection.Emitare unsupported in native AOT- Dynamic generic instantiation (
MakeGenericType) may be trimmed
All JIT-dependent APIs are annotated with [RequiresUnreferencedCode] to surface these limitations at build time.