### 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 { }
```