Skip to content

Commit 12396b7

Browse files
feat: Add Hook Dependency Injection extension method with Hook instance (#513)
<!-- Please use this template for your pull request. --> <!-- Please use the sections that you need and delete other sections --> ## This PR <!-- add the description of the PR here --> In #512 I needed to tweak the sample AspNetCore application to pass Hook options to the MetricsHook. I noticed that in order to pass the options I needed to use the delegate based approach, while discarding the `serviceProvider`, like: ```csharp featureBuilder.AddHostedFeatureLifecycle() .AddHook(_ => new MetricsHook(metricsHookOptions)) ``` It would be simpler and easier for devs to interact with a third overload that allows them to pass an instance of the hook that they want to interact with, like so: ```csharp featureBuilder.AddHostedFeatureLifecycle() .AddHook(new MetricsHook()) ``` ### Related Issues <!-- add here the GitHub issue that this PR resolves if applicable --> ### Notes <!-- any additional notes for this PR --> ### Follow-up Tasks <!-- anything that is related to this PR but not done here should be noted under this section --> <!-- if there is a need for a new issue, please link it here --> ### How to test <!-- if applicable, add testing instructions under this section --> --------- Signed-off-by: Kyle Julian <38759683+kylejuliandev@users.noreply.github.com>
1 parent 883f4f3 commit 12396b7

File tree

3 files changed

+62
-0
lines changed

3 files changed

+62
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,7 @@ builder.Services.AddOpenFeature(featureBuilder => {
481481
.AddHostedFeatureLifecycle()
482482
.AddContext((contextBuilder, serviceProvider) => { /* Custom context configuration */ })
483483
.AddHook((serviceProvider) => new LoggingHook( /* Custom configuration */ ))
484+
.AddHook(new MetricsHook())
484485
.AddInMemoryProvider("name1")
485486
.AddInMemoryProvider("name2")
486487
.AddPolicyName(options => {

src/OpenFeature.DependencyInjection/OpenFeatureBuilderExtensions.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,33 @@ public static OpenFeatureBuilder AddHook<THook>(this OpenFeatureBuilder builder,
278278
return builder.AddHook(typeof(THook).Name, implementationFactory);
279279
}
280280

281+
/// <summary>
282+
/// Adds a feature hook to the service collection. Hooks added here are not domain-bound.
283+
/// </summary>
284+
/// <typeparam name="THook">The type of<see cref="Hook"/> to be added.</typeparam>
285+
/// <param name="builder">The <see cref="OpenFeatureBuilder"/> instance.</param>
286+
/// <param name="hook">Instance of Hook to inject into the OpenFeature context.</param>
287+
/// <returns>The <see cref="OpenFeatureBuilder"/> instance.</returns>
288+
public static OpenFeatureBuilder AddHook<THook>(this OpenFeatureBuilder builder, THook hook)
289+
where THook : Hook
290+
{
291+
return builder.AddHook(typeof(THook).Name, hook);
292+
}
293+
294+
/// <summary>
295+
/// Adds a feature hook to the service collection with a specified name. Hooks added here are not domain-bound.
296+
/// </summary>
297+
/// <typeparam name="THook">The type of<see cref="Hook"/> to be added.</typeparam>
298+
/// <param name="builder">The <see cref="OpenFeatureBuilder"/> instance.</param>
299+
/// <param name="hookName">The name of the <see cref="Hook"/> that is being added.</param>
300+
/// <param name="hook">Instance of Hook to inject into the OpenFeature context.</param>
301+
/// <returns>The <see cref="OpenFeatureBuilder"/> instance.</returns>
302+
public static OpenFeatureBuilder AddHook<THook>(this OpenFeatureBuilder builder, string hookName, THook hook)
303+
where THook : Hook
304+
{
305+
return builder.AddHook(hookName, _ => hook);
306+
}
307+
281308
/// <summary>
282309
/// Adds a feature hook to the service collection using a factory method and specified name. Hooks added here are not domain-bound.
283310
/// </summary>

test/OpenFeature.DependencyInjection.Tests/OpenFeatureBuilderExtensionsTests.cs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,40 @@ public void AddHook_WithSpecifiedNameAndImplementationFactory_AsKeyedService()
302302
Assert.NotNull(hook);
303303
}
304304

305+
[Fact]
306+
public void AddHook_WithInstance_AddsHookAsKeyedService()
307+
{
308+
// Arrange
309+
var expectedHook = new NoOpHook();
310+
_systemUnderTest.AddHook(expectedHook);
311+
312+
var serviceProvider = _services.BuildServiceProvider();
313+
314+
// Act
315+
var actualHook = serviceProvider.GetKeyedService<Hook>("NoOpHook");
316+
317+
// Assert
318+
Assert.NotNull(actualHook);
319+
Assert.Equal(expectedHook, actualHook);
320+
}
321+
322+
[Fact]
323+
public void AddHook_WithSpecifiedNameAndInstance_AddsHookAsKeyedService()
324+
{
325+
// Arrange
326+
var expectedHook = new NoOpHook();
327+
_systemUnderTest.AddHook("custom-hook", expectedHook);
328+
329+
var serviceProvider = _services.BuildServiceProvider();
330+
331+
// Act
332+
var actualHook = serviceProvider.GetKeyedService<Hook>("custom-hook");
333+
334+
// Assert
335+
Assert.NotNull(actualHook);
336+
Assert.Equal(expectedHook, actualHook);
337+
}
338+
305339
[Fact]
306340
public void AddHandler_AddsEventHandlerDelegateWrapperAsKeyedService()
307341
{

0 commit comments

Comments
 (0)