Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,7 @@ builder.Services.AddOpenFeature(featureBuilder => {
.AddHostedFeatureLifecycle()
.AddContext((contextBuilder, serviceProvider) => { /* Custom context configuration */ })
.AddHook((serviceProvider) => new LoggingHook( /* Custom configuration */ ))
.AddHook(new MetricsHook())
.AddInMemoryProvider("name1")
.AddInMemoryProvider("name2")
.AddPolicyName(options => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,37 @@ public static OpenFeatureBuilder AddHook<THook>(this OpenFeatureBuilder builder,
return builder.AddHook(typeof(THook).Name, implementationFactory);
}

/// <summary>
/// Adds a feature hook to the service collection. Hooks added here are not domain-bound.
/// </summary>
/// <typeparam name="THook">The type of<see cref="Hook"/> to be added.</typeparam>
/// <param name="builder">The <see cref="OpenFeatureBuilder"/> instance.</param>
/// <param name="hook">Instance of Hook to inject into the OpenFeature context.</param>
/// <returns>The <see cref="OpenFeatureBuilder"/> instance.</returns>
public static OpenFeatureBuilder AddHook<THook>(this OpenFeatureBuilder builder, THook hook)
where THook : Hook
{
return builder.AddHook(typeof(THook).Name, hook);
}

/// <summary>
/// Adds a feature hook to the service collection with a specified name. Hooks added here are not domain-bound.
/// </summary>
/// <typeparam name="THook">The type of<see cref="Hook"/> to be added.</typeparam>
/// <param name="builder">The <see cref="OpenFeatureBuilder"/> instance.</param>
/// <param name="hookName">The name of the <see cref="Hook"/> that is being added.</param>
/// <param name="hook">Instance of Hook to inject into the OpenFeature context.</param>
/// <returns>The <see cref="OpenFeatureBuilder"/> instance.</returns>
public static OpenFeatureBuilder AddHook<THook>(this OpenFeatureBuilder builder, string hookName, THook hook)
where THook : Hook
{
builder.Services.PostConfigure<OpenFeatureOptions>(options => options.AddHookName(hookName));

builder.Services.TryAddKeyedSingleton<Hook>(hookName, hook);

return builder;
}

/// <summary>
/// Adds a feature hook to the service collection using a factory method and specified name. Hooks added here are not domain-bound.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,40 @@ public void AddHook_WithSpecifiedNameAndImplementationFactory_AsKeyedService()
Assert.NotNull(hook);
}

[Fact]
public void AddHook_WithInstance_AddsHookAsKeyedService()
{
// Arrange
var expectedHook = new NoOpHook();
_systemUnderTest.AddHook(expectedHook);

var serviceProvider = _services.BuildServiceProvider();

// Act
var actualHook = serviceProvider.GetKeyedService<Hook>("NoOpHook");

// Assert
Assert.NotNull(actualHook);
Assert.Equal(expectedHook, actualHook);
}

[Fact]
public void AddHook_WithSpecifiedNameAndInstance_AddsHookAsKeyedService()
{
// Arrange
var expectedHook = new NoOpHook();
_systemUnderTest.AddHook("custom-hook", expectedHook);

var serviceProvider = _services.BuildServiceProvider();

// Act
var actualHook = serviceProvider.GetKeyedService<Hook>("custom-hook");

// Assert
Assert.NotNull(actualHook);
Assert.Equal(expectedHook, actualHook);
}

[Fact]
public void AddHandler_AddsEventHandlerDelegateWrapperAsKeyedService()
{
Expand Down