Skip to content

Commit

Permalink
Introduce HostBuilder Feature (#13)
Browse files Browse the repository at this point in the history
* Introduce HostBuilder Feature

* Clean up
  • Loading branch information
pmdevers committed Nov 2, 2023
1 parent fbe3fc3 commit b2b9b4b
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 10 deletions.
16 changes: 16 additions & 0 deletions src/Featurize.AspNetCore/IHostFeature.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using Microsoft.Extensions.Hosting;

namespace Featurize.AspNetCore;

/// <summary>
/// Describes a HostBuilder feature.
/// </summary>
/// <seealso cref="Featurize.IFeature" />
public interface IHostFeature : IFeature
{
/// <summary>
/// Allow the feature to configure the Host specific properties.
/// </summary>
/// <param name="hostBuilder">The Host builder.</param>
void Configure(IHostBuilder hostBuilder);
}
17 changes: 17 additions & 0 deletions src/Featurize.AspNetCore/WebApplicationBuilderExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,18 @@ public static WebApplication BuildWithFeatures(this WebApplicationBuilder builde
{
var features = builder.Features();

foreach (var feature in features.GetHostFeatures())
{
feature.Configure(builder.Host);
}

foreach (var feature in features.GetServiceCollectionFeatures())
{
feature.Configure(builder.Services);
}

var application = builder.Build();

foreach (var feature in features.GetUseFeatures())
{
feature.Use(application);
Expand All @@ -44,6 +51,16 @@ public static WebApplication BuildWithFeatures(this WebApplicationBuilder builde
/// </summary>
/// <param name="features">The <see cref="IFeatureCollection"/>.</param>
/// <returns>List of <see cref="IUseFeature"/>.</returns>
[Pure]
public static IEnumerable<IUseFeature> GetUseFeatures(this IFeatureCollection features)
=> features.OfType<IUseFeature>();

/// <summary>
/// Gets all features implmenting <see cref="IHostFeature"/>.
/// </summary>
/// <param name="features">The <see cref="IFeatureCollection"/>.</param>
/// <returns>List of <see cref="IHostFeature"/>.</returns>
[Pure]
public static IEnumerable<IHostFeature> GetHostFeatures(this IFeatureCollection features)
=> features.OfType<IHostFeature>();
}
Expand Down
2 changes: 1 addition & 1 deletion src/Featurize/DependencyFeatures/DependencyResolver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ internal static IEnumerable<T> GetDependencies<T>(T item, HashSet<T> source)
foreach (var dep in dependencies)
{
var depType = dep.GetGenericArguments()[0];
var d = source.FirstOrDefault(x=> x.GetType() == depType);
var d = source.FirstOrDefault(x => x?.GetType() == depType);

if (d is null)
throw new InvalidOperationException($"Dependenvy '{dep.Name}' required for '{item.GetType().Name}' has not been registered.");
Expand Down
13 changes: 5 additions & 8 deletions src/Featurize/DependencyFeatures/IDependsOn.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection.Metadata.Ecma335;
using System.Text;
using System.Threading.Tasks;
namespace Featurize.SortFeatures;

namespace Featurize.SortFeatures;
/// <summary>
/// Marks a feature that it depends on <typeparamref name="TFeature"/>.
/// </summary>
/// <typeparam name="TFeature">The feature that it depends on.</typeparam>
public interface IDependsOn<TFeature>
where TFeature : IFeature
{
Expand Down
41 changes: 41 additions & 0 deletions test/Featurize.AspNetCore/HostBuilder_Features.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using Microsoft.Extensions.Hosting;

namespace Featurize.AspNetCore.Tests;
public class HostBuilder_Features
{
[Test]
public void should_be_used()
{
var feature = new SimpleHostFeature();
var builder = WebApplication.CreateBuilder();
builder.Features()
.Add(feature);

var app = builder.BuildWithFeatures();

feature.IsUsed.Should().BeTrue();

var act = () => app.Services.GetRequiredService<SimpleHostRegistration>();

act.Should().NotThrow<InvalidOperationException>();

}
}

internal class SimpleHostFeature : IHostFeature
{
public bool IsUsed { get; set; }

public void Configure(IHostBuilder hostBuilder)
{
IsUsed = true;

hostBuilder.ConfigureServices(s =>
{
s.AddTransient<SimpleHostRegistration>();
});

}
}

public class SimpleHostRegistration { }
2 changes: 1 addition & 1 deletion test/Featurize.Tests/ConfigurableFeature.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public void Configure_Should_Be_Called()
features.Add(configureFeature);
features.Add(optionsFeature);

var c = features.Get<ConfigurableFeature>();
var c = features.Get<ConfigurableFeature>()!;
c.ConfigCalled.Should().BeTrue();
}
}
Expand Down

0 comments on commit b2b9b4b

Please sign in to comment.