diff --git a/framework/src/BBT.Aether.Core/BBT/Aether/DependencyInjection/ServiceScopeFactoryExtensions.cs b/framework/src/BBT.Aether.Core/BBT/Aether/DependencyInjection/ServiceScopeFactoryExtensions.cs
new file mode 100644
index 0000000..ed68f98
--- /dev/null
+++ b/framework/src/BBT.Aether.Core/BBT/Aether/DependencyInjection/ServiceScopeFactoryExtensions.cs
@@ -0,0 +1,160 @@
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using BBT.Aether.Uow;
+using Microsoft.Extensions.DependencyInjection;
+
+namespace BBT.Aether.DependencyInjection;
+
+///
+/// Extension methods for IServiceScopeFactory.
+///
+public static class ServiceScopeFactoryExtensions
+{
+ ///
+ /// Executes the given action within a new dependency injection scope and a new unit of work.
+ /// Manages ambient service provider propagation.
+ ///
+ /// The service scope factory.
+ /// The action to execute, receiving the scoped service provider.
+ /// Unit of work options. Defaults to a new UoW with default settings.
+ /// Cancellation token.
+ /// A task representing the asynchronous operation.
+ public static async Task ExecuteInNewUnitOfWorkScopeAsync(
+ this IServiceScopeFactory scopeFactory,
+ Func action,
+ UnitOfWorkOptions? options = null,
+ CancellationToken cancellationToken = default)
+ {
+ await using var scope = scopeFactory.CreateAsyncScope();
+ var sp = scope.ServiceProvider;
+
+ // Propagate ambient service provider for the new scope
+ var previousAmbient = AmbientServiceProvider.Current;
+ AmbientServiceProvider.Current = sp;
+
+ try
+ {
+ var uowManager = sp.GetRequiredService();
+
+ // Begin UnitOfWork
+ await using var uow = await uowManager.BeginAsync(options, cancellationToken);
+
+ // Execute action
+ await action(sp);
+
+ // Commit UnitOfWork
+ await uow.CommitAsync(cancellationToken);
+ }
+ finally
+ {
+ // Restore previous ambient context
+ AmbientServiceProvider.Current = previousAmbient;
+ }
+ }
+
+ ///
+ /// Executes the given function within a new dependency injection scope and a new unit of work, returning a result.
+ /// Manages ambient service provider propagation.
+ ///
+ /// The type of the result.
+ /// The service scope factory.
+ /// The function to execute, receiving the scoped service provider.
+ /// Unit of work options. Defaults to a new UoW with default settings.
+ /// Cancellation token.
+ /// The result of the function execution.
+ public static async Task ExecuteInNewUnitOfWorkScopeAsync(
+ this IServiceScopeFactory scopeFactory,
+ Func> func,
+ UnitOfWorkOptions? options = null,
+ CancellationToken cancellationToken = default)
+ {
+ await using var scope = scopeFactory.CreateAsyncScope();
+ var sp = scope.ServiceProvider;
+
+ // Propagate ambient service provider for the new scope
+ var previousAmbient = AmbientServiceProvider.Current;
+ AmbientServiceProvider.Current = sp;
+
+ try
+ {
+ var uowManager = sp.GetRequiredService();
+
+ // Begin UnitOfWork
+ await using var uow = await uowManager.BeginAsync(options, cancellationToken);
+
+ // Execute function
+ var result = await func(sp);
+
+ // Commit UnitOfWork
+ await uow.CommitAsync(cancellationToken);
+
+ return result;
+ }
+ finally
+ {
+ // Restore previous ambient context
+ AmbientServiceProvider.Current = previousAmbient;
+ }
+ }
+
+ ///
+ /// Executes the given action within a new dependency injection scope without starting a unit of work.
+ /// Manages ambient service provider propagation.
+ ///
+ /// The service scope factory.
+ /// The action to execute, receiving the scoped service provider.
+ /// A task representing the asynchronous operation.
+ public static async Task ExecuteInNewScopeAsync(
+ this IServiceScopeFactory scopeFactory,
+ Func action)
+ {
+ await using var scope = scopeFactory.CreateAsyncScope();
+ var sp = scope.ServiceProvider;
+
+ // Propagate ambient service provider for the new scope
+ var previousAmbient = AmbientServiceProvider.Current;
+ AmbientServiceProvider.Current = sp;
+
+ try
+ {
+ await action(sp);
+ }
+ finally
+ {
+ // Restore previous ambient context
+ AmbientServiceProvider.Current = previousAmbient;
+ }
+ }
+
+ ///
+ /// Executes the given function within a new dependency injection scope without starting a unit of work, returning a result.
+ /// Manages ambient service provider propagation.
+ ///
+ /// The type of the result.
+ /// The service scope factory.
+ /// The function to execute, receiving the scoped service provider.
+ /// The result of the function execution.
+ public static async Task ExecuteInNewScopeAsync(
+ this IServiceScopeFactory scopeFactory,
+ Func> func)
+ {
+ await using var scope = scopeFactory.CreateAsyncScope();
+ var sp = scope.ServiceProvider;
+
+ // Propagate ambient service provider for the new scope
+ var previousAmbient = AmbientServiceProvider.Current;
+ AmbientServiceProvider.Current = sp;
+
+ try
+ {
+ return await func(sp);
+ }
+ finally
+ {
+ // Restore previous ambient context
+ AmbientServiceProvider.Current = previousAmbient;
+ }
+ }
+}
+}
diff --git a/framework/src/BBT.Aether.Core/BBT/Aether/Results/ResultExtensions.cs b/framework/src/BBT.Aether.Core/BBT/Aether/Results/ResultExtensions.cs
index 7d0ec63..4e7e6f2 100644
--- a/framework/src/BBT.Aether.Core/BBT/Aether/Results/ResultExtensions.cs
+++ b/framework/src/BBT.Aether.Core/BBT/Aether/Results/ResultExtensions.cs
@@ -231,6 +231,28 @@ public static Result Tap(this Result result, Action sideEffect)
public static Result Ensure(this Result result, Func predicate, Error error)
=> result.IsSuccess && !predicate(result.Value!) ? Result.Fail(error) : result;
+ ///
+ /// Ensures a predicate is satisfied, otherwise returns an error (lazy evaluation).
+ ///
+ /// Value type
+ /// The source result
+ /// Condition that must be true
+ /// Function to create error if predicate fails
+ /// The original result if predicate passes, otherwise a failure
+ public static Result Ensure(this Result result, Func predicate, Func errorFactory)
+ => result.IsSuccess && !predicate(result.Value!) ? Result.Fail(errorFactory()) : result;
+
+ ///
+ /// Ensures a predicate is satisfied, otherwise returns an error (lazy evaluation with value access).
+ ///
+ /// Value type
+ /// The source result
+ /// Condition that must be true
+ /// Function to create error based on the value if predicate fails
+ /// The original result if predicate passes, otherwise a failure
+ public static Result Ensure(this Result result, Func predicate, Func errorFactory)
+ => result.IsSuccess && !predicate(result.Value!) ? Result.Fail(errorFactory(result.Value!)) : result;
+
///
/// Executes a side effect on failure without altering the error.
/// Useful for logging, alerting, or cleanup actions on failure.
@@ -349,6 +371,34 @@ public static async Task> EnsureAsync(this Result result, Func.Fail(error);
}
+ ///
+ /// Async version of Ensure for sync Result with async predicate (lazy error evaluation).
+ ///
+ /// Value type
+ /// The source result
+ /// Async predicate that must be true
+ /// Function to create error if predicate fails
+ /// The original result if predicate passes, otherwise a failure
+ public static async Task> EnsureAsync(this Result result, Func> predicate, Func errorFactory)
+ {
+ if (!result.IsSuccess) return result;
+ return await predicate(result.Value!) ? result : Result.Fail(errorFactory());
+ }
+
+ ///
+ /// Async version of Ensure for sync Result with async predicate (lazy error evaluation with value access).
+ ///
+ /// Value type
+ /// The source result
+ /// Async predicate that must be true
+ /// Function to create error based on the value if predicate fails
+ /// The original result if predicate passes, otherwise a failure
+ public static async Task> EnsureAsync(this Result result, Func> predicate, Func errorFactory)
+ {
+ if (!result.IsSuccess) return result;
+ return await predicate(result.Value!) ? result : Result.Fail(errorFactory(result.Value!));
+ }
+
///
/// Async version of Map for Task-wrapped results.
///
@@ -458,6 +508,34 @@ public static async Task> EnsureAsync(this Task> task, Fu
return result.Ensure(predicate, error);
}
+ ///
+ /// Async version of Ensure for Task-wrapped results (lazy error evaluation).
+ ///
+ /// Value type
+ /// The source result task
+ /// Condition that must be true
+ /// Function to create error if predicate fails
+ /// The original result if predicate passes, otherwise a failure
+ public static async Task> EnsureAsync(this Task> task, Func predicate, Func errorFactory)
+ {
+ var result = await task;
+ return result.Ensure(predicate, errorFactory);
+ }
+
+ ///
+ /// Async version of Ensure for Task-wrapped results (lazy error evaluation with value access).
+ ///
+ /// Value type
+ /// The source result task
+ /// Condition that must be true
+ /// Function to create error based on the value if predicate fails
+ /// The original result if predicate passes, otherwise a failure
+ public static async Task> EnsureAsync(this Task> task, Func predicate, Func errorFactory)
+ {
+ var result = await task;
+ return result.Ensure(predicate, errorFactory);
+ }
+
///
/// Async version of Match for Task-wrapped results with sync handlers.
///