Two resolvers, four entry points

Two resolvers, four entry points

Part 2: Two resolvers, four entry points In part 1 we established the shape of the problem: handlers want IIdentity and IPrincipal handed to them as plain parameters, but something above the handler has to produce those — lazily, correctly, for whichever execution context we’re in, and before any transaction opens. Let’s build that layer. The resolvers At the center are two resolvers with an identical shape: check a cache, resolve if empty, store the result back. public sealed class CurrentIdentityResolver( ICurrentIdentity currentIdentity, HttpIdentityFactory httpIdentityFactory ) : IIdentityResolver { public async ValueTask<IIdentity> Resolve(CancellationToken cancellationToken) { if (currentIdentity.Identity is { } resolved) { return resolved; } var identity = await httpIdentityFactory.Create(cancellationToken); currentIdentity.Change(identity); return identity; } } ICurrentIdentity is an ambient holder — a singleton backed by AsyncLocal, so its value flows with the current async context (an HTTP request, a background job, a message handler) rather than living in a DI scope. Its Change method returns an IDisposable that restores the previous value, which is what makes nested contexts safe. The first call within a context resolves identity and caches it there. The principal resolver layers on top, and this is where the execution contexts converge into a single decision: public sealed class CurrentPrincipalResolver( IIdentityResolver identityResolver, ICurrentPrincipal currentPrincipal, UserPrincipalFactory userPrincipalFactory ) : ICurrentPrincipalResolver { public async ValueTask<IPrincipal> Resolve(CancellationToken cancellationToken) { if (currentPrincipal.Principal is { } resolved) { return resolved; } var identity = await identityResolver.Resolve(cancellationToken); IPrincipal principal = identity switch { AnonymousIdentity => new AnonymousPrincipal(), SystemIdentity => new SystemPrincipal(), UserIdentity user…

Continue reading →

 

Want more insights? Join Grow With Caliber - our career elevating newsletter and get our take on the future of work delivered weekly.