Skip to content

CEL for .NET

Compile, type-check, and evaluate CEL against your POCOs — no protobuf required.

Why this exists

The Common Expression Language is the “safe expression” choice for policy, config, and rule engines — small, sandboxed, non-Turing-complete, with a stable spec and a corpus of conformance tests.

Cel.NET is a clean-room C# / .NET 10 port of the spec. It runs 2,082 of the 2,257 applicable cel-spec conformance cases (92%), ships as five small libraries with no required external dependencies, and treats POCOs as first-class — protobuf is optional.

Idiomatic C#

Records, init-only properties, pattern matching, immutable builders. No generated parser; the lexer and Pratt parser are hand-rolled and read like a textbook.

POCO-first

Bind plain CLR objects directly — program.Eval(new { user, request }). Reflection adapter for the easy path; ITypeProvider for proto and other custom type systems.

Compile once, eval many

CelExpression.Compile(...) returns a CompiledProgram you reuse across millions of evaluations. The static type check happens once.

Pluggable extensions

strings, math, encoders, sets, optionals, bindings, network, block — all opt-in. Bring your own via the ICelExtension interface.

Quick taste

using DotnetCel;
using DotnetCel.Extensions;
using DotnetCel.Types;
var env = CelEnv.NewBuilder()
.Use(StringsExtension.Instance)
.Use(MathExtension.Instance)
.Variable("user", CelTypes.Object("User"))
.Build();
var program = CelExpression.Compile(
"user.name.startsWith('a') && math.abs(user.age) >= 18",
env);
bool ok = (bool)program.Eval(new {
user = new { Name = "alice", Age = 25 }
})!;

Where to next

Need API details?

The reference covers every public type, overload, and the language standard library.

Curious about coverage?

See the conformance status for a pass-rate breakdown across all cel-spec test files.