.NET Libraries
All FrenchExDev libraries are under intensive development, including the generators and Diem. I am building reusable foundations while developing Diem as the product that will progressively bring them together. The longer-term destination includes a software factory Lab with GitLab, GitLab CI and nodes, defined by a project such as MyLocalHost.Diem.Lab.
The groups below describe current responsibilities. Short examples follow the inspected source and tests as of 9 September 2026; they are excerpts for their corresponding projects, whose test suites were not executed for this documentation update. See the ecosystem overview for the product trajectory and development practices for validation.
Result (FrenchExDev.Net.Result)
Use explicit outcomes when failure is part of an operation's contract. Result, Result<T> and Result<T, TError> distinguish success from failure; Map transforms a successful value, Bind composes another result, and Recover supplies a replacement value.
These two cases come from ResultExtensionsTests:
using System.ComponentModel.DataAnnotations;
using FrenchExDev.Net.Result;
var length = await Result<string>.Success("hello")
.MapAsync(value => Task.FromResult(value.Length));
var recovered = Result<string>.Failure(new ValidationResult("err"))
.Recover(_ => "fallback");using System.ComponentModel.DataAnnotations;
using FrenchExDev.Net.Result;
var length = await Result<string>.Success("hello")
.MapAsync(value => Task.FromResult(value.Length));
var recovered = Result<string>.Failure(new ValidationResult("err"))
.Recover(_ => "fallback");The tests cover success, failure propagation and recovery. Callbacks can still throw, and ValueOrThrow() deliberately throws on failure; callers choose where to inspect or unwrap results. Source and tests (ouvre dans une nouvelle fenêtre) · Practical guide.
Options
Option<T> represents an expected absence through Some and None. It includes matching, LINQ, collection and asynchronous extensions, plus conversions to Result. A missing optional setting can therefore remain distinct from a failed operation. Unit and CsCheck property tests exercise this behavior. Source (ouvre dans une nouvelle fenêtre).
Union
OneOf<T1, T2> and the three- and four-case variants represent alternatives with typed matching. The testing package supplies assertions for the selected case. This is a small runtime library; each consumer still defines what those alternatives mean. Source (ouvre dans une nouvelle fenêtre).
Guard
Guard.Against throws for rejected arguments, Guard.ToResult returns validation outcomes, and Guard.Ensure checks invariants or postconditions. These entry points make the chosen failure policy visible at the call site. Tests and assertion helpers accompany the checks. Source (ouvre dans une nouvelle fenêtre).
Builder (FrenchExDev.Net.Builder)
Builder supports object construction that needs asynchronous validation, nested collections or references between objects. Its Roslyn generator emits fluent construction APIs; the runtime handles validation, cached construction and reference resolution.
BuildAsync() returns a result containing a Reference<T>. Existing consumer tests resolve it with result.ValueOrThrow().Resolved(); the Traefik example shows the complete sequence.
The Builder tests include concurrent calls sharing one construction, validation failures and parent/child graphs with back-references. These mechanisms are still evolving with their consumers. Source and tests (ouvre dans une nouvelle fenêtre) · Practical guide.
Injectable
Injectable describes service lifetimes and interface contracts with attributes. Roslyn generators produce registrations for Microsoft DI, DryIoc and Simple Injector; analyzers inspect problems such as lifetime mismatches and captive dependencies. Container integration tests exercise generated registrations. Source (ouvre dans une nouvelle fenêtre) · Design article.
Mapper
Mapper currently provides IMapper<TSource, TTarget>, mapping attributes and testing assertions. It gives application code a mapping contract; the inspected projects do not yet contain a mapping generator that implements those mappings automatically. Source (ouvre dans une nouvelle fenêtre).
Mediator
Mediator defines requests, commands, queries, handlers, notifications and pipeline behaviors. FakeMediator supports tests of callers. The current package supplies these contracts and testing tools; an application dispatcher is still to be implemented. Source (ouvre dans une nouvelle fenêtre).
Clock
IClock wraps time access, delays and timers. SystemClock uses TimeProvider; FakeClock wraps FakeTimeProvider, allowing tests to advance time and trigger pending timers. This supports repeatable timeout and scheduling tests without waiting for wall-clock time. Source (ouvre dans une nouvelle fenêtre).
HttpClient
The FrenchExDev IHttpClient is a small HTTP GET abstraction. Its testing package supplies sequential responses and builders. The current FakeHttpClient constructor accepts an array or a list:
using System.Net;
using FrenchExDev.Net.HttpClient.Testing;
var fake = new FakeHttpClient(new[]
{
new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new StringContent("data")
},
new HttpResponseMessage(HttpStatusCode.NotFound)
});
var response = await fake.GetAsync("https://example.test/document");using System.Net;
using FrenchExDev.Net.HttpClient.Testing;
var fake = new FakeHttpClient(new[]
{
new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new StringContent("data")
},
new HttpResponseMessage(HttpStatusCode.NotFound)
});
var response = await fake.GetAsync("https://example.test/document");The fake returns the supplied responses in order without a network request. Supply enough responses for the calls under test. Alpine.Version uses this abstraction; DockAi uses ASP.NET Core HTTP clients and IHttpClientFactory. Source and fakes (ouvre dans une nouvelle fenêtre).
Finite State Machine (FrenchExDev.Net.FiniteStateMachine)
The FSM models asynchronous transitions through Dynamic, Typed and Rich APIs. It includes guards, entry/exit actions, hierarchical states, parallel regions, deferred events, timers and graph inspection.
A shortened path from DynamicFireTests uses the actual FireAsync entry point:
using FrenchExDev.Net.FiniteStateMachine.Dynamic;
var definition = new DynamicStateMachineBuilder()
.InitialState("Created")
.FinalState("Delivered")
.When("Created")
.On("Submit").TransitionTo("Submitted")
.When("Submitted")
.On("Deliver").TransitionTo("Delivered")
.Build();
var machine = definition.Value!.CreateMachine();
var transition = await machine.FireAsync("Submit");using FrenchExDev.Net.FiniteStateMachine.Dynamic;
var definition = new DynamicStateMachineBuilder()
.InitialState("Created")
.FinalState("Delivered")
.When("Created")
.On("Submit").TransitionTo("Submitted")
.When("Submitted")
.On("Deliver").TransitionTo("Delivered")
.Build();
var machine = definition.Value!.CreateMachine();
var transition = await machine.FireAsync("Submit");The result describes an accepted or denied transition. Tests cover transitions, guards, hierarchy and generation; testing utilities explore paths through the graph. Source (ouvre dans une nouvelle fenêtre) · Practical guide.
Reactive
IEventStream<T>, EventStream<T> and their extensions provide event publication and subscription. TestEventStream<T> makes emissions observable in tests. Consumers remain responsible for subscription lifetimes and the behavior attached to events. Source (ouvre dans une nouvelle fenêtre).
Saga
SagaOrchestrator<TContext> coordinates steps and compensations around a saga context and store contract. The testing package includes an in-memory store. This provides a basis for recoverable workflows; durable storage and external side effects depend on the chosen integration. Source (ouvre dans une nouvelle fenêtre).
Outbox
Outbox defines messages, storage and processing contracts. Its EF Core integration includes EfCoreOutbox, a message configuration and a SaveChangesInterceptor for collecting domain events. An in-memory implementation supports tests. Delivery guarantees still depend on transaction boundaries, processing and the receiving system. Source (ouvre dans une nouvelle fenêtre).
Dsl — Meta-Metamodel (FrenchExDev.Net.Dsl)
Dsl describes concepts, properties, references, constraints and inheritance through C# metamodel declarations. Its generator discovers declarations and emits a MetamodelRegistry. The purpose is to give domain-specific languages shared modeling primitives. Source (ouvre dans une nouvelle fenêtre) · M0–M3 modeling guide.
Ddd — Domain-Driven Design DSL (FrenchExDev.Net.Ddd)
Ddd describes aggregates, entities, value objects, relationships, commands and events using attributes. Its invariant generator gathers declared rules into validation code. Persistence generation belongs to Entity.Dsl and its DDD bridge, described next. Source (ouvre dans une nouvelle fenêtre) · DDD guide.
Entity.Dsl
Entity.Dsl generates persistence artifacts from entity descriptions: EF Core configurations, DbContext, repositories and units of work. Generator tests are the entry point for examining the current emitted output and supported model shapes. Source (ouvre dans une nouvelle fenêtre).
Ddd.Entity.Dsl
This bridge translates DDD metadata into the entity DSL's persistence model. It keeps the responsibilities explicit: Ddd expresses the domain; Entity.Dsl produces persistence artifacts; the bridge connects their metadata. Source (ouvre dans une nouvelle fenêtre).
Requirements — Feature Tracking DSL (FrenchExDev.Net.Requirements)
Requirements represents features and acceptance criteria in C# and generates a RequirementRegistry. Typed references make declarations navigable and refactorable.
The coverage analyzer remains a placeholder: REQ100 is declared, but Initialize registers no analysis action. Compilation therefore does not enforce a complete specification/implementation/test chain for every acceptance criterion. Test execution and evidence collection are separate concerns. Source (ouvre dans une nouvelle fenêtre) · Design series · Requirements-as-Code implementation and evidence.
Diem — Content Management Framework (FrenchExDev.Net.Diem)
I started Diem to give FrenchExDev a product dimension and bring the components together. Its content, administration, page and workflow DSLs develop that application model alongside the infrastructure work.
Several generator entry points are empty or contain TODOs. The complete generation of Blazor administration, EF persistence and REST/GraphQL APIs remains a design target. The Lab is part of the proposed product architecture; its exposure and access controls are configurable.
The intended convergence will let me write MyLocalHost.Diem.Lab: a software factory adapted to my own laptop, composing GitLab, GitLab CI and nodes through reusable wrappers and bundles. Source (ouvre dans une nouvelle fenêtre) · Product presentation · Product, architecture and specification · CMF design series.
BinaryWrapper (FrenchExDev.Net.BinaryWrapper)
BinaryWrapper turns versioned CLI descriptions into C# command APIs. Design projects collect help output; Roslyn generates command types, builders and clients; runtime services resolve executables, construct argument arrays and process results or events.
Collected metadata supports version annotations and guards. Correct execution also depends on the installed executable, parser coverage and its environment. The nine wrapper families illustrate these differences with source and test references. Framework source (ouvre dans une nouvelle fenêtre) · Practical guide.
Wrapper.Versioning (FrenchExDev.Net.Wrapper.Versioning)
Wrapper.Versioning collects versioned items and runs download, transformation and save stages. GitHub/GitLab collectors and pipeline options support filtering and incremental collection for generators and bundles.
Its runner limits concurrency with SemaphoreSlim. BinaryWrapper's design runner separately uses System.Threading.Channels. Saved inputs make generation inspectable, but a successful download alone does not establish that a generated integration works. Source (ouvre dans une nouvelle fenêtre) · Typed configurations.