Application Definitions base classes. The small but very helpful packege that can help you to organize your ASP.NET Core application.
$ dotnet add package Calabonga.AspNetCore.AppDefinitionsСборка позволяет навести порядок в вашем Program.cs. Можно всё разложить "по полочкам". А еще можно реализовать систему плагинов. Чтобы воспользоваться сборкой надо просто установить nuget-пакет Calabonga.AspNetCore.AppDefinitions.
NET8На ряду с версией для NET6.0 добавлена версия для NET8.0. В параметры пакетов добавлены следующие настройки:
А также исправлены некоторые недочеты в процесс формирования и публикации nuget-пакета.
Добавлена обработка дубликатов AppDefinitions, которые были найдены в сторонних сборках. Дополнительная информация о найденых дубликатах определений теперь выводиться в процессе отладке (DEBUG) включенном в настройках логирования.
Информация при уровне логирования LogLevel = "Debug":

Информация при уровне логирования LogLevel = "Information":

Создан шаблон для генерации проекта ASP.NET Web API c AppDefinitions. То есть, чтобы не устанавливать каждый раз Calabonga.AspNetCore.AppDefinitions nuget-пакет в новый (в пустой) проект, можно воспользоваться уже готовым шаблоном, который создаст приложение с установленным nuget-пакетом (плюс еще Serilog). Это гораздо быстрее и удобнее. Я использую этот шаблона в своих видео на своём канале boosty.to/calabonga.
Проект шаблона с инструкцией по использованию.
// Вместо этого (instead of)
builder.AddDefinitions(typeof(Program));
// использовать этот (use this to add definitions for application)
const string moduleFolder = "Modules:Folder";
var modulesPath = builder.Configuration[moduleFolder] ?? throw new ArgumentNullException(moduleFolder);
builder.AddDefinitionsWithModules(modulesPath, typeof(Program));
[15:43:03 DBG] [AppDefinitions]: From Program
[15:43:03 DBG] [AppDefinitions]: AuthorizationDefinition (Program) (Enabled: Yes)
[15:43:03 DBG] [AppDefinitions]: AuthorizeEndpoints (Program) (Enabled: Yes)
[15:43:03 DBG] [AppDefinitions]: AutomapperDefinition (Program) (Enabled: Yes)
[15:43:03 DBG] [AppDefinitions]: CommonDefinition (Program) (Enabled: Yes)
[15:43:03 DBG] [AppDefinitions]: ContainerDefinition (Program) (Enabled: Yes)
[15:43:03 DBG] [AppDefinitions]: CorsDefinition (Program) (Enabled: Yes)
[15:43:03 DBG] [AppDefinitions]: DataSeedingDefinition (Program) (Enabled: Yes)
[15:43:03 DBG] [AppDefinitions]: DbContextDefinition (Program) (Enabled: Yes)
[15:43:03 DBG] [AppDefinitions]: ErrorHandlingDefinition (Program) (Enabled: Yes)
[15:43:03 DBG] [AppDefinitions]: ETagGeneratorDefinition (Program) (Enabled: Yes)
[15:43:03 DBG] [AppDefinitions]: EventItemEndpoints (Program) (Enabled: Yes)
[15:43:03 DBG] [AppDefinitions]: FluentValidationDefinition (Program) (Enabled: Yes)
[15:43:03 DBG] [AppDefinitions]: MediatorDefinition (Program) (Enabled: Yes)
[15:43:03 DBG] [AppDefinitions]: OpenIddictDefinition (Program) (Enabled: Yes)
[15:43:03 DBG] [AppDefinitions]: ProfilesEndpoints (Program) (Enabled: Yes)
[15:43:03 DBG] [AppDefinitions]: SwaggerDefinition (Program) (Enabled: Yes)
[15:43:03 DBG] [AppDefinitions]: TokenEndpoints (Program) (Enabled: Yes)
[15:43:03 DBG] [AppDefinitions]: UnitOfWorkDefinition (Program) (Enabled: Yes)
[15:43:03 DBG] From Program assemblies totally AppDefinitions found: 18
[15:43:04 DBG] Total AppDefinitions applied: 18
Exported свойство задано как False, то есть, не экспортировать данный AppDefinition. Например, если регистрацию конечной точки (endpoint) WeatherForcast слелать через определение (AppDefinition), то экспорт мог бы выглядеть так:public class WeatherForecastEndpoints : AppDefinition
{
/// <summary>
/// Enables or disables export definition as a content for module that can be exported.
/// </summary>
/// /// <remarks>Default values is <c>False</c></remarks>
public override bool Exported => true;
public override void ConfigureApplication(WebApplication app)
{
app.MapGet("/weatherforecast", WeatherGet)
.ProducesProblem(401)
.Produces<WeatherForecast[]>()
.WithName("GetWeatherForecast")
.WithTags("ModuleTwo")
.WithOpenApi()
.RequireAuthorization(policyNames: CookieAuthenticationDefaults.AuthenticationScheme + ",OpenIddict.Validation.AspNetCore");
}
// [FeatureGroupName("Weather")]
private WeatherForecast[] WeatherGet([FromServices] ILogger<WeatherForecastEndpoints> logger)
{
var summaries = new[] { "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" };
var forecast = Enumerable.Range(1, 5).Select(index =>
new WeatherForecast
(
DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
Random.Shared.Next(-20, 55),
summaries[Random.Shared.Next(summaries.Length)]
))
.ToArray();
logger.LogInformation("WeatherForecast request execute at [{Time}].", DateTime.UtcNow);
return forecast;
}
}
IServiceCollection в метод ConfigureServices. Теперь достаточно только WebApplicationBuilder. Следовательно при переходе на версию 2.0.0 нужно просто удалить лишние зависимости. Например, регистрация FluentValidation это выглядит так:/// <summary>
/// FluentValidation registration as Application definition
/// </summary>
public class FluentValidationDefinition : AppDefinition
{
/// <summary>
/// Configure services for current application
/// </summary>
/// <param name="builder"></param>
public override void ConfigureServices(WebApplicationBuilder builder)
{
builder.Services.Configure<ApiBehaviorOptions>(options =>
{
options.SuppressModelStateInvalidFilter = true;
});
builder.Services.AddValidatorsFromAssembly(typeof(Program).Assembly);
}
}
builder.AddDefinitions(typeof(Program));
Можно воспользоваться инструментов Visual Studio:

Или можно просто прописать в файле проекта, но тогда надо будет подставить правильную версию пакета. Посмотреть последнюю актуальную версию можно на nuget.org.

Создайте папку Definitions в вашем проекте. В папке создайте ContainerDefinition и унаследуйте его от AppDefinition, как показано ниже на картинке. После этого сделайте переопределение метода ConfigureServices и/или других методов и свойств.

На этой картинке переопределено два метода:

Подключите ваши определения как показано на этой картинке:

Таких определений (наследников от AppDefinition) может быть сколько угодно (конечно же в разумных пределах). После старта приложения вы увидите (если включен уровень логирования Debug) список всех подключенных определений (AppDefinition). Например, в моём случае их 18.

У каждого из созданных вами наследников от AppDefinition есть свойство Enabled и OrderIndex. Угадайте, что можно с ними (с AppDefinitionами) сделать?
Application Definitions base classes. The small but very helpful package that can help you to organize your ASP.NET Core application.
You can find more information in my blog Nimble Framework