### Create Web App with Source Generation (C#) Source: https://github.com/ncosentino/needlr/blob/main/docs/getting-started.md Illustrates setting up and running an ASP.NET Core web application using Needlr with source generation. It demonstrates how to build the web application and includes an example of adding a minimal API endpoint using a plugin. ```csharp using NexusLabs.Needlr.AspNet; using NexusLabs.Needlr.Injection; using NexusLabs.Needlr.Injection.SourceGen; // Create and run a web application var webApplication = new Syringe() .UsingSourceGen() .ForWebApplication() .BuildWebApplication(); await webApplication.RunAsync(); // Add a minimal API endpoint using a plugin internal sealed class HelloWorldPlugin : IWebApplicationPlugin { public void Configure(WebApplicationPluginOptions options) { options.WebApplication.MapGet("/", () => "Hello, World!"); } } ``` -------------------------------- ### Install Needlr Packages for Bundle Strategy (XML) Source: https://github.com/ncosentino/needlr/blob/main/docs/getting-started.md Installs the Needlr bundle package, which includes both source generation and reflection strategies with automatic fallback. This provides flexibility for applications that might need both discovery methods. ```xml ``` -------------------------------- ### Install Needlr Packages for Source Generation (XML) Source: https://github.com/ncosentino/needlr/blob/main/docs/getting-started.md Installs the core dependency injection, source generation, and ASP.NET Core integration packages for Needlr using the recommended source generation strategy. This is ideal for AOT-compiled applications and optimal startup performance. ```xml ``` -------------------------------- ### Configure Web Application with Reflection Source: https://github.com/ncosentino/needlr/blob/main/docs/getting-started.md Build a web application using `Syringe` configured with reflection. This is suitable for dynamic scenarios or when using features like Scrutor. ```csharp using NexusLabs.Needlr.Injection.Reflection; var webApplication = new Syringe() .UsingReflection() .ForWebApplication() .BuildWebApplication(); ``` -------------------------------- ### Create Web App with Reflection (C#) Source: https://github.com/ncosentino/needlr/blob/main/docs/getting-started.md Demonstrates creating and running an ASP.NET Core web application with Needlr using reflection-based discovery. This approach allows for runtime type registration. ```csharp using NexusLabs.Needlr.AspNet; using NexusLabs.Needlr.Injection; using NexusLabs.Needlr.Injection.Reflection; // Create and run a web application with reflection var webApplication = new Syringe() .UsingReflection() .ForWebApplication() .BuildWebApplication(); await webApplication.RunAsync(); ``` -------------------------------- ### VS Code Extension Setup and Debugging Source: https://github.com/ncosentino/needlr/blob/main/ide-extensions/README.md These bash commands outline the steps to set up and debug the VS Code extension. It includes navigating to the extension directory, installing dependencies, compiling the code, and instructions for debugging within VS Code. ```bash cd vscode npm install npm run compile # Press F5 in VS Code to debug ``` -------------------------------- ### Implement IHostPlugin for Post-Build Execution Source: https://github.com/ncosentino/needlr/blob/main/src/NexusLabs.Needlr.Hosting/Package.README.md This snippet shows how to implement the `IHostPlugin` interface. Plugins implementing this interface execute after the host has been built but before it starts running, allowing for initialization or setup tasks that depend on the built host's services. ```csharp public sealed class MyHostPlugin : IHostPlugin { public void Configure(HostPluginOptions options) { var service = options.Host.Services.GetRequiredService(); service.Initialize(); } } ``` -------------------------------- ### Install Needlr Packages for Reflection (XML) Source: https://github.com/ncosentino/needlr/blob/main/docs/getting-started.md Installs the core dependency injection, reflection-based discovery, and ASP.NET Core integration packages for Needlr. This option is suitable for applications requiring runtime type discovery or dynamic plugin loading. ```xml ``` -------------------------------- ### IWebApplicationPlugin Example (C#) Source: https://github.com/ncosentino/needlr/blob/main/docs/core-concepts.md Shows how to implement IWebApplicationPlugin to configure the WebApplication after it has been built. This example adds a health check endpoint and enables CORS. ```csharp public class MyAppPlugin : IWebApplicationPlugin { public void Configure(WebApplicationPluginOptions options) { options.WebApplication.MapGet("/health", () => "Healthy"); options.WebApplication.UseCors(); } } ``` -------------------------------- ### IWebApplicationBuilderPlugin Example (C#) Source: https://github.com/ncosentino/needlr/blob/main/docs/core-concepts.md Demonstrates implementing IWebApplicationBuilderPlugin to configure the WebApplicationBuilder. This example adds CORS services and loads a custom JSON configuration file. ```csharp public class MyBuilderPlugin : IWebApplicationBuilderPlugin { public void Configure(WebApplicationBuilderPluginOptions options) { options.Builder.Services.AddCors(); options.Builder.Configuration.AddJsonFile("custom.json"); } } ``` -------------------------------- ### Configure ServiceProvider with Auto-Configuration Source: https://github.com/ncosentino/needlr/blob/main/docs/getting-started.md Build a `ServiceProvider` using `Syringe`'s auto-configuration. This strategy attempts to use source generation first and falls back to reflection if necessary. ```csharp using NexusLabs.Needlr.Injection.Bundle; var serviceProvider = new Syringe() .UsingAutoConfiguration() // Tries source-gen first, falls back to reflection .BuildServiceProvider(); ``` -------------------------------- ### Create Console App Service Provider with Reflection (C#) Source: https://github.com/ncosentino/needlr/blob/main/docs/getting-started.md Shows how to create a service provider for a console application using Needlr's reflection-based discovery. Services are registered at runtime, and `MyService` is retrieved and executed. ```csharp using NexusLabs.Needlr.Injection; using NexusLabs.Needlr.Injection.Reflection; using Microsoft.Extensions.DependencyInjection; // Create a service provider with reflection-based discovery var serviceProvider = new Syringe() .UsingReflection() .BuildServiceProvider(); // Get your service (automatically registered at runtime) var myService = serviceProvider.GetRequiredService(); myService.DoWork(); ``` -------------------------------- ### Configure Web Application with Configuration Callback Source: https://github.com/ncosentino/needlr/blob/main/docs/getting-started.md Build a web application with `Syringe` using a configuration callback. This method allows you to customize the `WebApplicationBuilder` before the application is built, including configuration sources, service registrations, and logging. ```csharp var webApplication = new Syringe() .UsingSourceGen() // or .UsingReflection() .ForWebApplication() .UsingConfigurationCallback((builder, options) => { // Customize configuration sources builder.Configuration .SetBasePath(AppContext.BaseDirectory) .AddJsonFile("appsettings.local.json", optional: true) .AddEnvironmentVariables("MYAPP_"); // Add services before plugin registration builder.Services.AddSingleton(); // Configure logging builder.Logging.AddConsole(); builder.Logging.SetMinimumLevel(LogLevel.Debug); }) .BuildWebApplication(); ``` -------------------------------- ### Configure Web Application with Source Generation Source: https://github.com/ncosentino/needlr/blob/main/docs/getting-started.md Build a web application using `Syringe` configured with source generation. This is the recommended approach for AOT-compiled web applications. ```csharp using NexusLabs.Needlr.Injection.SourceGen; var webApplication = new Syringe() .UsingSourceGen() .ForWebApplication() .BuildWebApplication(); ``` -------------------------------- ### Configure Web Application with Web Application Factory Source: https://github.com/ncosentino/needlr/blob/main/docs/getting-started.md Build a web application using `Syringe` and a custom `WebApplicationFactory`. This is useful for integration testing scenarios where you need a pre-configured factory. ```csharp var webApplication = new Syringe() .UsingSourceGen() // or .UsingReflection() .ForWebApplication() .UsingWebApplicationFactory() .BuildWebApplication(); ``` -------------------------------- ### Create Console App Service Provider with Source Generation (C#) Source: https://github.com/ncosentino/needlr/blob/main/docs/getting-started.md Demonstrates creating a service provider for a console application using Needlr's source generation strategy. Services are automatically registered at compile time, and the `MyService` is retrieved and executed. ```csharp using NexusLabs.Needlr.Injection; using NexusLabs.Needlr.Injection.SourceGen; using Microsoft.Extensions.DependencyInjection; // Create a service provider with source-gen discovery var serviceProvider = new Syringe() .UsingSourceGen() .BuildServiceProvider(); // Get your service (automatically registered at compile time) var myService = serviceProvider.GetRequiredService(); myService.DoWork(); // Your service class - automatically discovered by source generator public class MyService { public void DoWork() { Console.WriteLine("Work is being done!"); } } ``` -------------------------------- ### Configure ServiceProvider with Reflection Source: https://github.com/ncosentino/needlr/blob/main/docs/getting-started.md Build a `ServiceProvider` using the `Syringe` container configured with reflection. This method is useful for dynamic scenarios where assemblies might not be known at compile time. ```csharp using NexusLabs.Needlr.Injection.Reflection; var serviceProvider = new Syringe() .UsingReflection() .BuildServiceProvider(); ``` -------------------------------- ### Configure ServiceProvider with Source Generation Source: https://github.com/ncosentino/needlr/blob/main/docs/getting-started.md Build a `ServiceProvider` using the `Syringe` container configured with source generation. This approach is suitable for Ahead-of-Time (AOT) compilation. ```csharp using NexusLabs.Needlr.Injection.SourceGen; var serviceProvider = new Syringe() .UsingSourceGen() .BuildServiceProvider(); ``` -------------------------------- ### IPostBuildServiceCollectionPlugin Example (C#) Source: https://github.com/ncosentino/needlr/blob/main/docs/core-concepts.md Illustrates implementing IPostBuildServiceCollectionPlugin to execute logic after the main service collection has been built. This allows access to already registered services for further configuration. ```csharp public class MyPostBuildPlugin : IPostBuildServiceCollectionPlugin { public void Configure(PostBuildServiceCollectionPluginOptions options) { // Access built services var myService = options.Services.GetService(); // Additional configuration } } ``` -------------------------------- ### Configure Web Application with Custom Options Source: https://github.com/ncosentino/needlr/blob/main/docs/getting-started.md Build a web application with `Syringe` using custom options for the `WebApplicationBuilder`. This allows fine-grained control over default settings, logging, and application naming. ```csharp var webApplication = new Syringe() .UsingSourceGen() // or .UsingReflection() .ForWebApplication() .UsingOptions(() => CreateWebApplicationOptions .Default .UsingStartupConsoleLogger() .UsingApplicationName("MyApp")) .BuildWebApplication(); ``` -------------------------------- ### IServiceCollectionPlugin Example (C#) Source: https://github.com/ncosentino/needlr/blob/main/docs/core-concepts.md Shows how to implement the IServiceCollectionPlugin interface to configure services during the initial registration phase. This example adds a singleton service and logs a message. ```csharp public class MyServicePlugin : IServiceCollectionPlugin { public void Configure(ServiceCollectionPluginOptions options) { options.Services.AddSingleton(); options.Logger.LogInformation("Configured MyService"); } } ``` -------------------------------- ### Configure Syringe with Source Generation or Reflection (C#) Source: https://github.com/ncosentino/needlr/blob/main/README.md Demonstrates how to initialize the `Syringe` class, the main entry point for Needlr configuration. It shows examples for both the recommended source generation approach and the reflection approach for dynamic scenarios. Both examples configure an assembly provider to scan for types within assemblies containing 'MyApp'. ```csharp // Source generation approach (recommended) var syringe = new Syringe() .UsingSourceGen() .UsingAssemblyProvider(builder => builder .MatchingAssemblies(x => x.Contains("MyApp")) .Build()); // Reflection approach (dynamic scenarios) var syringe = new Syringe() .UsingReflection() .UsingScrutorTypeRegistrar() .UsingAssemblyProvider(builder => builder .MatchingAssemblies(x => x.Contains("MyApp")) .Build()); ``` -------------------------------- ### Configure Syringe with Source Generation or Reflection Source: https://github.com/ncosentino/needlr/blob/main/docs/getting-started.md Configure the Syringe dependency injection container using either source generation (recommended for AOT) or reflection with Scrutor for dynamic scenarios. Both methods involve setting up an assembly provider to match specific assemblies. ```csharp var syringe = new Syringe() .UsingSourceGen() .UsingAssemblyProvider(builder => builder .MatchingAssemblies(x => x.Contains("MyApp")) .Build()); var syringe = new Syringe() .UsingReflection() .UsingScrutorTypeRegistrar() .UsingAssemblyProvider(builder => builder .MatchingAssemblies(x => x.Contains("MyApp")) .Build()); ``` -------------------------------- ### FusionCache Integration Example with [DeferToContainer] in C# Source: https://github.com/ncosentino/needlr/blob/main/docs/advanced-usage.md An example of integrating Needlr with a hypothetical CacheProviderGenerator, showcasing the use of the [DeferToContainer] attribute for multiple cache providers. This example illustrates how to define cache providers and their dependencies in the cache project and how they are resolved in the host application. ```csharp // In your cache providers project namespace MyApp.Caching; public interface ICacheProvider { } // The CacheProviderGenerator will add: // public sealed partial class EngageFeedCacheProvider(ICacheProvider _cacheProvider) [DeferToContainer(typeof(ICacheProvider))] [CacheProvider("EngageFeed")] public partial class EngageFeedCacheProvider { } [DeferToContainer(typeof(ICacheProvider), typeof(ILogger))] [CacheProvider("UserProfile")] public partial class UserProfileCacheProvider { } ``` ```csharp // In your host application var app = new Syringe() .UsingSourceGen() .ForWebApplication() .BuildWebApplication(); // Both cache providers are correctly registered with their dependencies resolved ``` -------------------------------- ### C# Complete Example: GenerateFactory Attribute Source: https://github.com/ncosentino/needlr/blob/main/docs/factories.md This example demonstrates the usage of the `[GenerateFactory]` attribute to automatically generate a factory for the `EmailSender` class. It shows how to define a service with mixed parameters and how to use the generated factory in another service (`NotificationService`) to create instances with specific runtime configurations. ```csharp using NexusLabs.Needlr.Generators; using MyApp.Generated; // Define your service with mixed parameters [GenerateFactory] public sealed class EmailSender { private readonly ISmtpClient _smtp; private readonly ILogger _logger; public string FromAddress { get; } /// Creates a new email sender. /// SMTP client for sending emails. /// Logger for diagnostics. /// The sender email address. public EmailSender(ISmtpClient smtp, ILogger logger, string fromAddress) { _smtp = smtp; _logger = logger; FromAddress = fromAddress; } public Task SendAsync(string to, string subject, string body) { /* ... */ } } // Use the generated factory public class NotificationService { private readonly IEmailSenderFactory _emailFactory; public NotificationService(IEmailSenderFactory emailFactory) { _emailFactory = emailFactory; } public async Task NotifyUserAsync(User user, string message) { // Create sender with appropriate from address var sender = _emailFactory.Create("noreply@myapp.com"); await sender.SendAsync(user.Email, "Notification", message); } public async Task NotifySupportAsync(string issue) { var sender = _emailFactory.Create("support@myapp.com"); await sender.SendAsync("team@myapp.com", "Support Issue", issue); } } ``` -------------------------------- ### C# Example: Fixed Validation Method Running Source: https://github.com/ncosentino/needlr/blob/main/docs/analyzers/NDLRGEN019.md Presents the corrected version of the C# code example where the validation method runs. By setting `ValidateOnStart = true` in the `Options` attribute, the `CheckSettings` method is now invoked. ```csharp using NexusLabs.Needlr.Generators; // ✅ ValidateOnStart = true enables the validation method [Options(ValidateMethod = "CheckSettings", ValidateOnStart = true)] public class FeatureFlags { public bool EnableBeta { get; set; } public int MaxUsers { get; set; } public IEnumerable CheckSettings() { if (EnableBeta && MaxUsers > 100) yield return "Beta features limited to 100 users"; } } ``` -------------------------------- ### Example of a Custom Service Class (C#) Source: https://github.com/ncosentino/needlr/blob/main/README.md Provides an example of a custom service class, `WeatherProvider`, that can be automatically registered by Needlr. This class demonstrates dependency injection of `IConfiguration` and has a method to retrieve weather data. ```csharp internal class WeatherProvider { private readonly IConfiguration _config; public WeatherProvider(IConfiguration config) { _config = config; } public WeatherData GetWeather() { // Implementation } } ``` -------------------------------- ### Configure WebApplicationBuilder with IWebApplicationBuilderPlugin in C# Source: https://github.com/ncosentino/needlr/blob/main/docs/plugin-development.md Implement IWebApplicationBuilderPlugin to configure the WebApplicationBuilder before the application is built. This allows for setting up authentication, authorization, Kestrel limits, and adding configuration sources. ```csharp public class SecurityPlugin : IWebApplicationBuilderPlugin { public void Configure(WebApplicationBuilderPluginOptions options) { // Configure services options.Builder.Services.AddAuthentication() .AddJwtBearer(opts => { opts.Authority = options.Builder.Configuration["Auth:Authority"]; }); options.Builder.Services.AddAuthorization(opts => { opts.AddPolicy("AdminOnly", policy => policy.RequireRole("Admin")); }); // Configure Kestrel options.Builder.WebHost.ConfigureKestrel(serverOptions => { serverOptions.Limits.MaxRequestBodySize = 10 * 1024 * 1024; // 10MB }); // Add configuration sources options.Builder.Configuration.AddJsonFile("security.json", optional: true); options.Logger.LogInformation("Security configured"); } } ``` -------------------------------- ### Configure WebApplication with IWebApplicationPlugin in C# Source: https://github.com/ncosentino/needlr/blob/main/docs/plugin-development.md Utilize IWebApplicationPlugin to configure the WebApplication after it has been built. This is the place for setting up the middleware pipeline, authentication, authorization, and mapping API endpoints. ```csharp public class ApiPlugin : IWebApplicationPlugin { public void Configure(WebApplicationPluginOptions options) { var app = options.WebApplication; // Configure middleware pipeline if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseAuthentication(); app.UseAuthorization(); // Map endpoints app.MapGet("/api/health", () => Results.Ok(new { Status = "Healthy" })) .WithName("HealthCheck") .WithOpenApi(); app.MapPost("/api/data", async (DataRequest request, IDataService service) => { var result = await service.ProcessAsync(request); return Results.Ok(result); }) .RequireAuthorization("AdminOnly"); options.Logger.LogInformation("API endpoints configured"); } } ``` -------------------------------- ### Deterministic Execution with Same Plugin Order (C#) Source: https://github.com/ncosentino/needlr/blob/main/docs/plugin-development.md Demonstrates how plugins with the same `PluginOrder` value are executed deterministically based on alphabetical sorting of their fully qualified type names. ```csharp // Both have Order = 0, so they execute alphabetically public class AuditPlugin : IServiceCollectionPlugin { } // Executes first public class ZipCodePlugin : IServiceCollectionPlugin { } // Executes second ``` -------------------------------- ### Implement IHostApplicationBuilderPlugin for Configuration Source: https://github.com/ncosentino/needlr/blob/main/src/NexusLabs.Needlr.Hosting/Package.README.md This snippet illustrates the implementation of the `IHostApplicationBuilderPlugin` interface. This plugin runs during the host builder configuration phase, allowing for the registration of services before the host is built. ```csharp public sealed class MyBuilderPlugin : IHostApplicationBuilderPlugin { public void Configure(HostApplicationBuilderPluginOptions options) { options.Builder.Services.AddSingleton(); } } ``` -------------------------------- ### Control Interface Registration with RegisterAs Attribute Source: https://github.com/ncosentino/needlr/blob/main/docs/getting-started.md Explicitly control which interfaces a class is registered as using the `[RegisterAs]` attribute. By default, classes are registered as all their implemented interfaces. ```csharp public interface IReader { } public interface IWriter { } public interface ILogger { } // Only registered as IReader, not IWriter or ILogger [RegisterAs] public class FileService : IReader, IWriter, ILogger { } ``` -------------------------------- ### Configure WebApplicationBuilder with Callback (C#) Source: https://github.com/ncosentino/needlr/blob/main/docs/advanced-usage.md Demonstrates using the UsingConfigurationCallback method to gain fine-grained control over the WebApplicationBuilder. This includes conditional configuration based on environment, adding configuration sources like JSON files and environment variables, and configuring services and Kestrel. ```csharp var webApplication = new Syringe() .UsingSourceGen() // or .UsingReflection() .ForWebApplication() .UsingConfigurationCallback((builder, options) => { // Conditional configuration based on environment if (builder.Environment.IsEnvironment("Test")) { // Test-specific configuration builder.Configuration.AddJsonFile("appsettings.Test.json", optional: false); } else { // Production configuration builder.Configuration .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) .AddJsonFile($"appsettings.{builder.Environment.EnvironmentName}.json", optional: true, reloadOnChange: true); } // Add environment variables with custom prefix builder.Configuration.AddEnvironmentVariables("MYAPP_"); // Override with in-memory configuration for testing if (builder.Environment.IsDevelopment()) { builder.Configuration.AddInMemoryCollection(new Dictionary { ["DebugMode"] = "true", ["DetailedErrors"] = "true" }); } // Configure services before plugin registration builder.Services.Configure(opts => { opts.SerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; }); // Configure Kestrel builder.WebHost.ConfigureKestrel(serverOptions => { serverOptions.Limits.MaxRequestBodySize = 50 * 1024 * 1024; // 50MB }); }) .BuildWebApplication(); ``` -------------------------------- ### Configure WebApplicationSyringe for ASP.NET Core (C#) Source: https://github.com/ncosentino/needlr/blob/main/README.md Illustrates how to configure `Syringe` specifically for ASP.NET Core web applications using the `ForWebApplication()` method. This example also shows how to configure web application options using `UsingOptions` and build the web application instance. ```csharp var webApp = new Syringe() .UsingSourceGen() .ForWebApplication() .UsingOptions(() => CreateWebApplicationOptions.Default) .BuildWebApplication(); ``` -------------------------------- ### Run All Benchmarks Locally (Bash) Source: https://github.com/ncosentino/needlr/blob/main/docs/benchmarks.md This command navigates to the benchmark directory and executes all available benchmarks using the .NET CLI in Release configuration. The '--filter *' argument ensures all benchmarks are included. ```bash cd src/NexusLabs.Needlr.Benchmarks dotnet run -c Release -- --filter '*' ``` -------------------------------- ### Configure ServiceProvider with Custom Assembly Scanning Source: https://github.com/ncosentino/needlr/blob/main/docs/getting-started.md Build a `ServiceProvider` with custom assembly scanning rules. This allows you to specify which assemblies should be included in the dependency injection configuration, using either source generation or reflection. ```csharp var serviceProvider = new Syringe() .UsingSourceGen() // or .UsingReflection() .UsingAssemblyProvider(builder => builder .MatchingAssemblies(x => x.Contains("MyCompany") || x.Contains("MyApp")) .UseLibTestEntryOrdering() // Sort assemblies appropriately .Build()) .BuildServiceProvider(); ``` -------------------------------- ### Decorate Hosted Services with Needlr (C#) Source: https://github.com/ncosentino/needlr/blob/main/docs/hosted-services.md Illustrates how to apply decorators to all hosted services using the [DecoratorFor] attribute. This example adds timing and logging to the service's start process. ```csharp [DecoratorFor(Order = 0)] public sealed class TimingHostedServiceDecorator : IHostedService { private readonly IHostedService _inner; private readonly ILogger _logger; public TimingHostedServiceDecorator( IHostedService inner, ILogger logger) { _inner = inner; _logger = logger; } public async Task StartAsync(CancellationToken cancellationToken) { var sw = Stopwatch.StartNew(); await _inner.StartAsync(cancellationToken); _logger.LogInformation("Started {Type} in {Elapsed}ms", _inner.GetType().Name, sw.ElapsedMilliseconds); } public Task StopAsync(CancellationToken cancellationToken) => _inner.StopAsync(cancellationToken); } ``` -------------------------------- ### Example of Validation Method Not Found Error in C# Source: https://github.com/ncosentino/needlr/blob/main/docs/analyzers/NDLRGEN016.md Illustrates the NDLRGEN016 error scenario where the 'ValidateMethod' specified in the [Options] attribute does not exist on the target class. This code snippet shows the incorrect setup leading to the error. ```csharp using NexusLabs.Needlr.Generators; // NDLRGEN016: Method 'CheckValidity' not found on type 'DatabaseOptions' [Options(ValidateMethod = "CheckValidity", ValidateOnStart = true)] public class DatabaseOptions { public string ConnectionString { get; set; } = ""; // No method named "CheckValidity" exists! } ``` -------------------------------- ### Inspect Hosted Services and Constructor Parameters Source: https://github.com/ncosentino/needlr/blob/main/docs/service-catalog.md Demonstrates how to iterate through the `HostedServices` collection in the `IServiceCatalog`. For each hosted service, it prints its type name and then iterates through its constructor parameters, displaying the name and type name of each parameter. ```csharp foreach (var hostedService in catalog.HostedServices) { Console.WriteLine($"Hosted Service: {hostedService.ShortTypeName}"); foreach (var param in hostedService.ConstructorParameters) { Console.WriteLine($" - {param.Name}: {param.TypeName}"); } } ``` -------------------------------- ### Implement Custom Web Application Factory (C#) Source: https://github.com/ncosentino/needlr/blob/main/docs/advanced-usage.md Provides an example of creating a custom WebApplicationFactory by implementing the IWebApplicationFactory interface. This allows for detailed customization of Kestrel configuration, service configuration, logging, and middleware pipeline. ```csharp public class CustomWebApplicationFactory : IWebApplicationFactory { public WebApplication Create( CreateWebApplicationOptions options, Func createWebApplicationBuilderCallback) { var builder = createWebApplicationBuilderCallback(); // Custom Kestrel configuration builder.WebHost.ConfigureKestrel(serverOptions => { serverOptions.ListenAnyIP(5000, listenOptions => { listenOptions.Protocols = HttpProtocols.Http2; }); serverOptions.ListenAnyIP(5001, listenOptions => { listenOptions.UseHttps(); listenOptions.Protocols = HttpProtocols.Http1AndHttp2; }); }); // Custom service configuration builder.Services.Configure(options => { options.AllowSynchronousIO = true; }); // Add custom configuration sources builder.Configuration.AddJsonFile("custom-settings.json", optional: true); builder.Configuration.AddEnvironmentVariables("MYAPP_"); // Custom logging builder.Logging.ClearProviders(); builder.Logging.AddConsole(); builder.Logging.AddDebug(); var app = builder.Build(); // Custom middleware pipeline if (app.Environment.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/error"); app.UseHsts(); } app.UseHttpsRedirection(); app.UseResponseCompression(); return app; } } // Usage var webApp = new Syringe() .ForWebApplication() .UsingWebApplicationFactory() .BuildWebApplication(); ``` -------------------------------- ### Getting Detailed Diagnostics with VerifyWithDiagnostics() in C# Source: https://github.com/ncosentino/needlr/blob/main/docs/advanced-usage.md This example shows how to use `VerifyWithDiagnostics()` to obtain a detailed report of dependency injection container issues without throwing exceptions immediately. It checks the `IsValid` property of the result and prints a detailed report if issues are found, or throws an exception if needed. ```csharp var result = services.VerifyWithDiagnostics(); if (!result.IsValid) { Console.WriteLine(result.ToDetailedReport()); // ❌ Container verification found 2 issue(s): // // [LifetimeMismatch] Lifetime mismatch: ICacheService (Singleton) depends on IDbContext (Scoped) // ... } // Or throw if needed result.ThrowIfInvalid(); ``` -------------------------------- ### Plugin with Dependencies: Data Initialization (C#) Source: https://github.com/ncosentino/needlr/blob/main/docs/plugin-development.md This plugin demonstrates how to access services registered by other plugins using dependency injection. It retrieves a database context and a cache service to initialize the cache with data from the database. This approach is necessary as built-in plugins do not support constructor injection. Dependencies include `MyDbContext` and `IMemoryCache`. ```csharp public class DependentPlugin : IPostBuildServiceCollectionPlugin { public void Configure(PostBuildServiceCollectionPluginOptions options) { // Get services that were registered by other plugins var dbContext = options.ServiceProvider.GetRequiredService(); var cache = options.ServiceProvider.GetService(); if (cache != null) { // Initialize cache with data from database var initialData = dbContext.Settings.ToList(); foreach (var setting in initialData) { cache.Set(setting.Key, setting.Value); } } } } ``` -------------------------------- ### Run Specific Benchmarks Locally (Bash) Source: https://github.com/ncosentino/needlr/blob/main/docs/benchmarks.md This command navigates to the benchmark directory and runs benchmarks filtered by a specific pattern, such as '*Build*'. It uses the .NET CLI in Release configuration. ```bash cd src/NexusLabs.Needlr.Benchmarks dotnet run -c Release -- --filter '*Build*' ``` -------------------------------- ### Web Application Plugin Configuration in C# Source: https://github.com/ncosentino/needlr/blob/main/README.md Shows how to implement `IWebApplicationPlugin` to configure web application endpoints. This allows for modular addition of routes and logic to the ASP.NET Core application during its startup phase. ```csharp internal sealed class WeatherPlugin : IWebApplicationPlugin { public void Configure(WebApplicationPluginOptions options) { options.WebApplication.MapGet("/weather", (WeatherProvider weatherProvider) => { return Results.Ok(weatherProvider.GetWeather()); }); } } ``` -------------------------------- ### Register Multiple Services After Plugins with CreateWebApplicationOptions Source: https://github.com/ncosentino/needlr/blob/main/docs/advanced-usage.md Illustrates registering multiple post-plugin registration callbacks efficiently using the plural overload `UsingPostPluginRegistrationCallbacks` for web applications. This simplifies adding several configurations at once. ```csharp var webApplication = new Syringe() .ForWebApplication() .UsingOptions(() => CreateWebApplicationOptions.Default .UsingPostPluginRegistrationCallbacks( services => services.AddAuthentication(), services => services.AddAuthorization(), services => services.AddAntiforgery())) .BuildWebApplication(); ``` -------------------------------- ### Custom Type Filterer Example (C#) Source: https://github.com/ncosentino/needlr/blob/main/docs/core-concepts.md Demonstrates how to create a custom type filterer by implementing the ITypeFilterer interface. This example filters out types ending with 'Test' and those not in the 'MyCompany' namespace. ```csharp public class MyTypeFilterer : ITypeFilterer { public IEnumerable Filter(IEnumerable types) { return types.Where(t => !t.Name.EndsWith("Test") && t.Namespace?.StartsWith("MyCompany") == true); } } ``` -------------------------------- ### NDLRGEN018 Example: Validator Not Running Source: https://github.com/ncosentino/needlr/blob/main/docs/analyzers/NDLRGEN018.md Illustrates a C# code example where the NDLRGEN018 warning occurs because ValidateOnStart is implicitly false for the specified validator. This code snippet shows the problematic configuration. ```csharp using NexusLabs.Needlr.Generators; // NDLRGEN018: Validator 'PaymentOptionsValidator' will not run // because ValidateOnStart is false [Options(Validator = typeof(PaymentOptionsValidator))] public class PaymentOptions { public string MerchantId { get; set; } = ""; } public class PaymentOptionsValidator : IOptionsValidator { public IEnumerable Validate(PaymentOptions options) { if (string.IsNullOrEmpty(options.MerchantId)) yield return "MerchantId is required"; } } ``` -------------------------------- ### Manual Decoration with Dependency Injection Source: https://github.com/ncosentino/needlr/blob/main/docs/core-concepts.md Illustrates manual decoration using standard dependency injection practices. This method involves explicitly registering the service and then creating a decorator that takes the original service as a dependency. ```csharp services.AddSingleton(); services.AddSingleton(sp => new ServiceDecorator(sp.GetRequiredService())); ``` -------------------------------- ### NDLRGEN018 Example: Fixed Code with Enabled Validator Source: https://github.com/ncosentino/needlr/blob/main/docs/analyzers/NDLRGEN018.md Presents the corrected version of the C# code example where the NDLRGEN018 warning is resolved by explicitly setting ValidateOnStart to true. This ensures the PaymentOptionsValidator is active. ```csharp using NexusLabs.Needlr.Generators; // ✅ ValidateOnStart = true enables the validator [Options(Validator = typeof(PaymentOptionsValidator), ValidateOnStart = true)] public class PaymentOptions { public string MerchantId { get; set; } = ""; } public class PaymentOptionsValidator : IOptionsValidator { public IEnumerable Validate(PaymentOptions options) { if (string.IsNullOrEmpty(options.MerchantId)) yield return "MerchantId is required"; } } ``` -------------------------------- ### Generated Proxy Example Implementing Interface (C#) Source: https://github.com/ncosentino/needlr/blob/main/docs/analyzers/NDLRCOR008.md Shows an example of a C# source-generated proxy class for an interceptor, highlighting how it implements the target service's interface to facilitate interception. ```csharp // Generated proxy internal sealed class OrderService_InterceptorProxy : IOrderService { private readonly OrderService _target; private readonly IServiceProvider _serviceProvider; public Order GetOrder(int id) { // Interceptor chain logic... } } ``` -------------------------------- ### Minimal Web API with Source Generation in C# Source: https://github.com/ncosentino/needlr/blob/main/README.md An example of setting up a minimal ASP.NET Core Web API using Needlr with source generation. It demonstrates automatic registration of custom types and defining API endpoints, including a `WeatherProvider` that uses configuration. ```csharp using NexusLabs.Needlr.AspNet; using NexusLabs.Needlr.Injection; using NexusLabs.Needlr.Injection.SourceGen; var webApplication = new Syringe() .UsingSourceGen() .ForWebApplication() .BuildWebApplication(); await webApplication.RunAsync(); internal sealed class WeatherPlugin : IWebApplicationPlugin { public void Configure(WebApplicationPluginOptions options) { options.WebApplication.MapGet("/weather", (WeatherProvider weatherProvider) => { return Results.Ok(weatherProvider.GetWeather()); }); } } internal sealed class WeatherProvider(IConfiguration config) { public object GetWeather() { var weatherConfig = config.GetSection("Weather"); return new { TemperatureC = weatherConfig.GetValue("TemperatureCelsius"), Summary = weatherConfig.GetValue("Summary"), }; } } ``` -------------------------------- ### Web Application Builder Plugin Configuration in C# Source: https://github.com/ncosentino/needlr/blob/main/README.md Illustrates the implementation of `IWebApplicationBuilderPlugin` for configuring services within the `WebApplicationBuilder`. This is useful for integrating third-party libraries or custom service registrations before the application is built. ```csharp public sealed class CarterWebApplicationBuilderPlugin : IWebApplicationBuilderPlugin { public void Configure(WebApplicationBuilderPluginOptions options) { options.Logger.LogInformation("Configuring Carter services..."); options.Builder.Services.AddCarter(); } } ``` -------------------------------- ### C# Example: ValidateMethod Not Running Warning Source: https://github.com/ncosentino/needlr/blob/main/docs/analyzers/NDLRGEN019.md Illustrates a C# code example that triggers the NDLRGEN019 warning. The `CheckSettings` method is specified in the `Options` attribute, but `ValidateOnStart` is implicitly false, preventing the method from running. ```csharp using NexusLabs.Needlr.Generators; // NDLRGEN019: ValidateMethod 'CheckSettings' will not run // because ValidateOnStart is false [Options(ValidateMethod = "CheckSettings")] public class FeatureFlags { public bool EnableBeta { get; set; } public int MaxUsers { get; set; } public IEnumerable CheckSettings() { if (EnableBeta && MaxUsers > 100) yield return "Beta features limited to 100 users"; } } ``` -------------------------------- ### Plugin Order Control Example (C#) Source: https://github.com/ncosentino/needlr/blob/main/docs/core-concepts.md Illustrates how to control the execution order of plugins using the [PluginOrder] attribute. Lower attribute values result in earlier execution. Plugins with the same order are sorted alphabetically. ```csharp // Control plugin execution order [PluginOrder(-100)] // Executes first public class InfrastructurePlugin : IServiceCollectionPlugin { } [PluginOrder(100)] // Executes last public class ValidationPlugin : IServiceCollectionPlugin { } ``` -------------------------------- ### Install Needlr via NuGet Package Manager (Reflection) Source: https://github.com/ncosentino/needlr/blob/main/docs/index.md This XML snippet shows how to install the necessary NexusLabs.Needlr packages for reflection-based dependency injection in a .NET project. It includes packages for injection and reflection-based injection. ```xml ``` -------------------------------- ### Concurrent Execution Example (BatchTool) Source: https://github.com/ncosentino/needlr/blob/main/CLAUDE.md A comprehensive example demonstrating concurrent execution within a single message using the BatchTool. It includes initializing a swarm, spawning agents, defining tasks, batching todos, and performing file operations. ```javascript [BatchTool]: // Initialize swarm mcp__claude-flow__swarm_init { topology: "mesh", maxAgents: 6 } mcp__claude-flow__agent_spawn { type: "researcher" } mcp__claude-flow__agent_spawn { type: "coder" } mcp__claude-flow__agent_spawn { type: "tester" } // Spawn agents with Task tool Task("Research agent: Analyze requirements...") Task("Coder agent: Implement features...") Task("Tester agent: Create test suite...") // Batch todos TodoWrite { todos: [ {id: "1", content: "Research", status: "in_progress", priority: "high"}, {id: "2", content: "Design", status: "pending", priority: "high"}, {id: "3", content: "Implement", status: "pending", priority: "high"}, {id: "4", content: "Test", status: "pending", priority: "medium"}, {id: "5", content: "Document", status: "pending", priority: "low"} ]} // File operations Bash "mkdir -p app/{src,tests,docs}" Write "app/src/index.js" Write "app/tests/index.test.js" Write "app/docs/README.md" ``` -------------------------------- ### Example of Invalid OpenDecoratorFor Usage - C# Source: https://github.com/ncosentino/needlr/blob/main/docs/open-generic-decorators.md Provides examples of common errors when using the `[OpenDecoratorFor]` attribute, highlighting violations of Needlr's compile-time analyzers. These include specifying a closed generic type, a non-generic decorator, or a decorator that doesn't implement the target interface. ```csharp // NDLRGEN006: Must use typeof(IHandler<>), not typeof(IHandler) [OpenDecoratorFor(typeof(IHandler))] // ❌ Error public class BadDecorator : IHandler { } // NDLRGEN007: Decorator must be generic with same parameter count [OpenDecoratorFor(typeof(IHandler<>))] public class BadDecorator : IHandler { } // ❌ Error - not generic // NDLRGEN008: Decorator must implement the interface [OpenDecoratorFor(typeof(IHandler<>))] public class BadDecorator { } // ❌ Error - doesn't implement IHandler ``` -------------------------------- ### Implement Custom Assembly Provider in C# Source: https://github.com/ncosentino/needlr/blob/main/docs/advanced-usage.md Shows how to implement the `IAssemblyProvider` interface to create custom logic for discovering and loading assemblies. This example loads DLLs from a specified directory and includes assemblies from the current application domain. ```csharp public class PluginAssemblyProvider : IAssemblyProvider { private readonly string _pluginDirectory; public PluginAssemblyProvider(string pluginDirectory) { _pluginDirectory = pluginDirectory; } public IEnumerable GetAssemblies() { var assemblies = new List(); // Load assemblies from plugin directory if (Directory.Exists(_pluginDirectory)) { var pluginFiles = Directory.GetFiles(_pluginDirectory, "*.dll"); foreach (var file in pluginFiles) { try { var assembly = Assembly.LoadFrom(file); assemblies.Add(assembly); } catch (Exception ex) { // Log and continue Console.WriteLine($"Failed to load {file}: {ex.Message}"); } } } // Also include current domain assemblies assemblies.AddRange(AppDomain.CurrentDomain.GetAssemblies()); return assemblies.Distinct(); } } ``` -------------------------------- ### C# SignalR Hub Path Constant Enforcement Source: https://github.com/ncosentino/needlr/blob/main/docs/analyzers/NDLRSIG001.md Demonstrates the incorrect and correct ways to define SignalR hub paths. The incorrect example uses a non-constant string, while the correct examples show using a 'const' string or a direct string literal, both of which are required for AOT compatibility. ```csharp public static class HubPaths { public static string ChatHub = "/chat"; // Not const! } [HubPath(HubPaths.ChatHub, typeof(ChatHub))] // NDLRSIG001 public class ChatHubRegistration : ISignalRHub { } ``` ```csharp public static class HubPaths { public const string ChatHub = "/chat"; // const is OK } [HubPath(HubPaths.ChatHub, typeof(ChatHub))] public class ChatHubRegistration : ISignalRHub { } // Or use a string literal directly [HubPath("/chat", typeof(ChatHub))] public class ChatHubRegistration : ISignalRHub { } ```