Application framework for .NET

Declare intent.
Generate the wiring.

Elarion turns modules, handlers, and attributes into deterministic, compile-time wiring. One annotated class becomes a use case, a service, a JSON-RPC method, an MCP tool, an HTTP endpoint, and a typed client — with no runtime reflection scanning.

Clients/GetClient.csC# 14
[RpcMethod("clients.get")]
public sealed class GetClient(IAppDbContext db)
  : IHandler<GetClient.Query, Result<Response>> {

  public sealed record Query(Guid Id);
  public sealed record Response(Guid Id, string Name);

  public async ValueTask<Result<Response>> HandleAsync(Query q, CancellationToken ct) {
    var client = await db.Clients
      .Where(c => c.Id == q.Id)
      .Select(c => new Response(c.Id, c.Name))
      .FirstOrDefaultAsync(ct);

    return client is null
      ? AppError.NotFound($"Client {q.Id} not found.")
      : client;
  }
}
.NET 9 · C# 14AOT & trim-safeZero runtime reflectionOpenTelemetry built inInspectable generated code
The core idea

One class. Every surface.

Your application assemblies declare modules and handlers. Source generators emit the registrations, transports, and contracts as ordinary DI code at build time. Nothing is discovered at startup, so missing wiring is a build error — never a runtime surprise.

  • No registration lists to keep in sync
  • Deterministic, AOT-friendly startup
  • The same handler, surfaced to humans and AI agents
How source generation works
[RpcMethod("clients.get")]sealed class GetClient: IHandler<Query, Result<…>>// one class. one source of truth.Registered serviceDI, no Program.cs entryJSON-RPC methodPOST /rpcMCP toolfor AI agentsHTTP endpointREST + ProblemDetailsTypeScript + Zod clientschema-exportedSOURCE-GENERATED · AOT-SAFE · NO RUNTIME REFLECTION
Capabilities

A thin host. A rich application surface.

Auto-detect application patterns, explicitly wire platform capabilities. Everything that can be derived from your code is generated for you.

Determinism

Build-time, not runtime

Reflection scanning
  • Wiring discovered by scanning the classpath at startup
  • Missing registration surfaces as a runtime exception
  • Reflection undermines trimming and AOT
  • A parallel registration list drifts from your code
Elarion compile-time
  • Wiring emitted as inspectable DI code at compile time
  • Missing wiring is a build error, caught in CI
  • Trim- and AOT-friendly by construction
  • Intent declared next to the type — one source of truth

The philosophy in one line

“Auto-detect application patterns, explicitly wire platform capabilities.

Repeating what your code already states — “I handle this request”, “I validate this command” — in a separate registration list creates a parallel model that drifts. Elarion declares intent next to the type and generates the wiring.

Read the full design rationale
Architecture

Layered, domain-neutral packages

A clean dependency direction: abstractions at the base, a reusable runtime above, and opt-in transports and data layers at the edge. The host stays a thin composition shell.

Your applicationModules · handlers · [attributes]
Elarion.GeneratorsCompile-time wiring · diagnostics · inspectable output
Elarion runtimeDecorator pipelines · Result<T> · scheduler · events
Opt-in transports & data
JSON-RPCHTTP / RESTMCP toolsEF CoreBlob storagePagingOutboxTelemetry

Ship your first module in minutes

Add the packages, declare a module, write a handler. The generators take care of the wiring, the transports, and the typed client.