Always emits Result<T>,
Result<T,TError>,
Unit, and
ResultExtensions —
then [TryWrap] generates
safe Try*() wrappers for every public method.
dotnet add package AutoResult.Generator
using AutoResult;
[TryWrap]
public partial class OrderService
{
public int GetOrderId(string name) => 42;
public void ProcessOrder(int id) { /* ... */ }
public async Task<Order> FetchOrderAsync(
int id,
CancellationToken ct = default)
=> await _repo.GetAsync(id, ct);
}
// ✨ AutoResult.g.cs
public partial class OrderService
{
public Result<int> TryGetOrderId(string name)
{
try { return Result<int>.Ok(GetOrderId(name)); }
catch (Exception ex) { return Result<int>.Fail(ex); }
}
public Result<Unit> TryProcessOrder(int id)
{
try { ProcessOrder(id); return Result<Unit>.Ok(Unit.Value); }
catch (Exception ex) { return Result<Unit>.Fail(ex); }
}
}
Result types, wrappers, and composition helpers generated into your project with zero runtime ceremony.
Result<T>, Result<T,TError>,
Unit, and ResultExtensions
are injected into every compilation automatically.
Add [TryWrap] to a partial class and the generator emits
Try*() wrappers for all public instance methods automatically.
Sync, void, async Task<T>, and async-void
Task methods are all handled correctly.
Compose success and failure paths with Map,
Bind, and Match
via ResultExtensions.
Methods already prefixed with Try are skipped automatically,
so generated wrappers never collide with existing APIs.
AR001 and AR002
catch misuse during the build, not after your app is already running.
From attribute to generated wrappers to railway-style composition.
using AutoResult;
[TryWrap]
public partial class OrderService
{
public int GetOrderId(string name) => 42;
public void ProcessOrder(int id) { /* ... */ }
public async Task<Order> FetchOrderAsync(int id, CancellationToken ct = default)
=> await _repo.GetAsync(id, ct);
}
// Auto-generated by AutoResult.Generator
public partial class OrderService
{
public Result<int> TryGetOrderId(string name)
{
try { return Result<int>.Ok(GetOrderId(name)); }
catch (Exception ex) { return Result<int>.Fail(ex); }
}
public Result<Unit> TryProcessOrder(int id)
{
try { ProcessOrder(id); return Result<Unit>.Ok(Unit.Value); }
catch (Exception ex) { return Result<Unit>.Fail(ex); }
}
public async Task<Result<Order>> TryFetchOrderAsync(int id, CancellationToken ct = default)
{
try { return Result<Order>.Ok(await FetchOrderAsync(id, ct)); }
catch (Exception ex) { return Result<Order>.Fail(ex); }
}
}
// Always available — no extra imports needed
var ok = Result<int>.Ok(42);
var err = Result<int>.Fail(new Exception("oops"));
ok.IsSuccess // true
ok.Value // 42
err.IsFailure // true
err.Error // Exception
// Void methods return Result<Unit>
Result<Unit>.Ok(Unit.Value)
// Two-type variant for typed errors
var r = Result<int, ValidationError>.Ok(42);
var e = Result<int, ValidationError>.Fail(new ValidationError("bad input"));
var result = await service.TryFetchOrderAsync(id)
.Map(order => order.ToDto()) // transform on success
.Bind(dto => ValidateDto(dto)) // chain result-returning call
.Match(
onSuccess: dto => Ok(dto), // map to HTTP result
onFailure: ex => Problem(ex.Message)
);
Misuse is reported by the compiler before it ships to production.
| Code | Severity | Description |
|---|---|---|
| AR001 | ✖ Error | [TryWrap] applied to a non-partial class |
| AR002 | ⚠ Warning | [TryWrap] class has no wrappable public methods |
Source-generated wrappers and auto-injected types without bringing in a runtime result library.
| Feature | AutoResult.Generator | FluentResults | OneOf |
|---|---|---|---|
| Compile-time wrapper generation | ✅ | ❌ | ❌ |
| Zero runtime overhead | ✅ | Minimal | Minimal |
| Core types auto-injected | ✅ | ❌ (install package) | ❌ (install package) |
| AOT-safe | ✅ | ✅ | ✅ |
| No extra dependency | ✅ | ❌ | ❌ |
More compile-time tooling from Justin Bannister and the Swevo ecosystem.
Generate object mapping code at build time. Browse the repo or published docs.
Compile-time FluentValidation registration and diagnostics with published docs.
Generate query specifications at compile time for clean LINQ composition.
GitHub ↗Compile-time CQRS dispatcher generation with strongly typed handlers.
GitHub ↗