Parsa99
Parsa99

Reputation: 496

ASP.NET Core | Register all configurations based on a marker interface

I have a problem of forgetting to register my services. I need a mechanism that the app would automatically find and register all my services based on a marker interfaces.

I wrote this code, which works fine:

public interface IService { }
public interface ISingletonService : IService { }
public interface IScopedService : IService { }
public interface ITransientService : IService { }

...

public static IEnumerable<T> TapWhere<T>(
    this IEnumerable<T> source,
    Func<T, bool> predicate,
    Action<T> action)
{
    foreach (var item in source)
    {
        if (predicate(item))
        {
            action(item);
        }

        yield return item;
    }
}

...

public static WebApplicationBuilder AddApplicationServices(this WebApplicationBuilder builder)
{
    var firstLevelAssemblies = Assembly.GetEntryAssembly()!
        .GetReferencedAssemblies()
        .Select(Assembly.Load);

    var secondLevelAssemblies = firstLevelAssemblies
        .SelectMany(x => x.GetReferencedAssemblies())
        .Select(Assembly.Load);
    
    _ = firstLevelAssemblies.Concat(secondLevelAssemblies)
        .DistinctBy(x => x.FullName)
        .SelectMany(x => x.GetTypes())
        .TapWhere(
            typeof(ISingletonService).IsAssignableFrom,
            x => builder.Services.AddSingleton(x))
        .TapWhere(
            typeof(IScopedService).IsAssignableFrom,
            x => builder.Services.AddScoped(x))
        .TapWhere(
            typeof(ITransientService).IsAssignableFrom,
            x => builder.Services.AddTransient(x))
        .ToArray();

    return builder;
}

I wanted to do the same with my configuration files. But I got stuck because unlike service registrations, the Configure<> method is generic and doesn't accept a Type instance.

public interface IConfig { }

...

_ = firstLevelAssemblies.Concat(secondLevelAssemblies)
    .DistinctBy(x => x.FullName)
    .SelectMany(x => x.GetTypes())
    .TapWhere(
        typeof(IConfig).IsAssignableFrom,
        x => builder.Services.Configure<>()) // :(
    .ToArray();

Is there any way I can automatically register my config files based on a marker interface?

Upvotes: 0

Views: 44

Answers (0)

Related Questions