diff --git a/Directory.Packages.props b/Directory.Packages.props index 5eff7b7..c340dc0 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -19,6 +19,8 @@ + + diff --git a/ForgingBlazor.slnx b/ForgingBlazor.slnx index aea312f..f7ac4e2 100644 --- a/ForgingBlazor.slnx +++ b/ForgingBlazor.slnx @@ -23,6 +23,7 @@ + diff --git a/src/NetEvolve.ForgingBlazor.Logging/ApplicationBuilderExtensions.cs b/src/NetEvolve.ForgingBlazor.Logging/ApplicationBuilderExtensions.cs new file mode 100644 index 0000000..73c9ef3 --- /dev/null +++ b/src/NetEvolve.ForgingBlazor.Logging/ApplicationBuilderExtensions.cs @@ -0,0 +1,115 @@ +namespace NetEvolve.ForgingBlazor.Logging; + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using NetEvolve.ForgingBlazor.Extensibility.Abstractions; + +/// +/// Provides extension methods for to configure and integrate logging services +/// into the Forging Blazor application pipeline. +/// +/// +/// This class offers a fluent API for adding logging capabilities to applications built with the Forging Blazor framework. +/// It provides both pre-configured default logging setups and flexible custom configurations to meet various logging requirements. +/// +public static class ApplicationBuilderExtensions +{ + /// + /// Configures the application with default logging providers, including console and debug output. + /// + /// + /// The instance that represents the application being configured. + /// This parameter serves as the entry point for adding logging services to the application's service collection. + /// + /// + /// The same instance that was passed in, enabling method chaining + /// and fluent configuration of additional application features. + /// + /// + /// Thrown when is . + /// + /// + /// + /// This method provides a convenient way to quickly set up logging with sensible defaults. + /// It automatically configures both console and debug logging providers, which are suitable + /// for most development and debugging scenarios. + /// + /// + /// The console provider outputs log messages to the standard console output, while the debug provider + /// writes to the debug output window in development environments and attached debuggers. + /// + /// + /// For production scenarios or when specific logging providers are required, consider using the + /// overload that accepts an delegate for custom configuration. + /// + /// + /// + /// + /// var builder = ApplicationBuilder.Create(); + /// builder.WithLogging(); + /// + /// + /// + public static IApplicationBuilder WithLogging(this IApplicationBuilder builder) => + builder.WithLogging(configure => configure.AddConsole().AddDebug()); + + /// + /// Configures the application with custom logging providers using a flexible configuration delegate. + /// + /// + /// The instance that represents the application being configured. + /// This parameter serves as the entry point for adding logging services to the application's service collection. + /// + /// + /// An delegate that provides fine-grained control over the logging configuration. + /// This delegate receives an instance that can be used to add logging providers, + /// set minimum log levels, add filters, and perform other logging-related configurations. + /// + /// + /// The same instance that was passed in, enabling method chaining + /// and fluent configuration of additional application features. + /// + /// + /// Thrown when is . + /// + /// + /// + /// This method offers maximum flexibility for configuring logging in the Forging Blazor application. + /// It allows developers to choose specific logging providers, configure log levels, add custom filters, + /// and integrate third-party logging frameworks according to their application's requirements. + /// + /// + /// The configuration delegate is executed immediately during the application builder's configuration phase, + /// ensuring that logging services are properly registered before any application components attempt to use them. + /// + /// + /// Common use cases include integrating structured logging providers (such as Serilog or NLog), + /// configuring cloud-based logging services (like Application Insights or AWS CloudWatch), + /// or setting up custom logging filters for performance optimization. + /// + /// + /// + /// Example with custom log levels and multiple providers: + /// + /// var builder = ApplicationBuilder.Create(); + /// builder.WithLogging(logging => + /// { + /// logging.SetMinimumLevel(LogLevel.Information); + /// logging.AddConsole(); + /// logging.AddEventLog(); + /// logging.AddFilter("Microsoft", LogLevel.Warning); + /// }); + /// + /// + /// + /// + /// + public static IApplicationBuilder WithLogging(this IApplicationBuilder builder, Action configure) + { + ArgumentNullException.ThrowIfNull(builder); + + _ = builder.Services.AddLogging(configure); + + return builder; + } +} diff --git a/src/NetEvolve.ForgingBlazor.Logging/NetEvolve.ForgingBlazor.Logging.csproj b/src/NetEvolve.ForgingBlazor.Logging/NetEvolve.ForgingBlazor.Logging.csproj new file mode 100644 index 0000000..15b8a12 --- /dev/null +++ b/src/NetEvolve.ForgingBlazor.Logging/NetEvolve.ForgingBlazor.Logging.csproj @@ -0,0 +1,17 @@ + + + $(_ProjectTargetFrameworks) + $(PackageTags);logging + + + + + + + + + + + + + diff --git a/src/NetEvolve.ForgingBlazor/ForgingBlazorApplicationBuilder.cs b/src/NetEvolve.ForgingBlazor/ForgingBlazorApplicationBuilder.cs index 269ce0e..620223a 100644 --- a/src/NetEvolve.ForgingBlazor/ForgingBlazorApplicationBuilder.cs +++ b/src/NetEvolve.ForgingBlazor/ForgingBlazorApplicationBuilder.cs @@ -1,6 +1,8 @@ namespace NetEvolve.ForgingBlazor; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; using NetEvolve.ForgingBlazor.Extensibility.Abstractions; /// @@ -98,6 +100,15 @@ public ForgingBlazorApplicationBuilder(string[] args) /// public IApplication Build() { + // Check if logging is already registered + if (!Services.IsServiceTypeRegistered()) + { + // Register NullLoggerFactory and NullLogger as defaults + _ = Services + .AddSingleton(NullLoggerFactory.Instance) + .AddSingleton(typeof(ILogger<>), typeof(NullLogger<>)); + } + var serviceProvider = Services.BuildServiceProvider(); return new ForgingBlazorApplication(_args, serviceProvider); diff --git a/src/NetEvolve.ForgingBlazor/ServiceCollectionExtensions.cs b/src/NetEvolve.ForgingBlazor/ServiceCollectionExtensions.cs new file mode 100644 index 0000000..dd39f82 --- /dev/null +++ b/src/NetEvolve.ForgingBlazor/ServiceCollectionExtensions.cs @@ -0,0 +1,12 @@ +namespace NetEvolve.ForgingBlazor; + +using System.CommandLine; +using Microsoft.Extensions.DependencyInjection; +using NetEvolve.ForgingBlazor.Commands; +using NetEvolve.ForgingBlazor.Extensibility.Abstractions; + +internal static class ServiceCollectionExtensions +{ + internal static bool IsServiceTypeRegistered(this IServiceCollection builder) + where T : class => builder.Any(x => x.ServiceType == typeof(T)); +} diff --git a/tests/NetEvolve.ForgingBlazor.Tests.Console/Program.cs b/tests/NetEvolve.ForgingBlazor.Tests.Console/Program.cs index 15299b7..b482879 100644 --- a/tests/NetEvolve.ForgingBlazor.Tests.Console/Program.cs +++ b/tests/NetEvolve.ForgingBlazor.Tests.Console/Program.cs @@ -1,6 +1,13 @@ using NetEvolve.ForgingBlazor; -var builder = ForgingBlazorApplicationBuilder.CreateDefaultBuilder(args); +var arguments = args; + +if (arguments.Length == 0) +{ + arguments = ["build"]; +} + +var builder = ForgingBlazorApplicationBuilder.CreateDefaultBuilder(arguments); var app = builder.Build();