### Install Reflection Extensions Package Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/docs/en/guide/reflection-extensions.md Add the package via the .NET CLI. ```bash dotnet add package AspectCore.Extensions.Reflection ``` -------------------------------- ### Verify .NET SDK installation Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/docs/en/development/building.md Check the currently installed .NET SDK versions and the active SDK version to ensure compatibility with project requirements. ```bash dotnet --list-sdks dotnet --version ``` -------------------------------- ### Example Configuration Structure Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/docs/en/guide/configuration-injection.md The JSON structure corresponding to the [ConfigurationValue] injection example. ```json { "creator": { "name": "lemon", "age": 24 } } ``` -------------------------------- ### Install AspectCore Configuration Package Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/docs/en/guide/configuration-injection.md Use the dotnet CLI to add the necessary package to your project. ```bash dotnet add package AspectCore.Extensions.Configuration ``` -------------------------------- ### Install DataAnnotations Package Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/docs/en/guide/data-validation.md Command to add the required NuGet package for DataAnnotations support. ```bash dotnet add package AspectCore.Extensions.DataAnnotations ``` -------------------------------- ### Install AspectCore Dependency Injection package Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/docs/en/getting-started/quick-start.md Add the required NuGet package to your .NET project. ```bash dotnet add package AspectCore.Extensions.DependencyInjection ``` -------------------------------- ### Conventional Commit examples Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/docs/en/development/contributing.md Examples of commit messages following the Conventional Commits specification. ```text feat: support ref and ref readonly return proxy generation (#385) feat: support C# 9 record type proxy generation (#384) ci: split coverage checks by test type (#380) docs(architecture): complete architecture section ``` -------------------------------- ### Replace Castle Windsor Container Setup Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/docs/guide/castle-migration/migration-guide.md Updates the service provider initialization from Castle Windsor to AspectCore's dynamic proxy provider. ```csharp // Replace Castle Windsor container setup // Before: var container = new WindsorContainer(); container.Install(FromAssembly.This()); var serviceProvider = container.Resolve(); // After: var services = new ServiceCollection(); services.ConfigureDynamicProxy(config => { /* ... */ }); services.AddDynamicProxy(); var serviceProvider = services.BuildDynamicProxyProvider(); ``` -------------------------------- ### Install AspectCore packages via .NET CLI Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/docs/en/getting-started/installation.md Commands to add common AspectCore packages to a .NET project. DependencyInjection is the recommended entry point as it includes core dependencies automatically. ```bash # Integrate with Microsoft.Extensions.DependencyInjection (the most common entry point) dotnet add package AspectCore.Extensions.DependencyInjection # Use only dynamic proxying or the built-in container dotnet add package AspectCore.Core # Use only the high-performance reflection extensions dotnet add package AspectCore.Extensions.Reflection ``` -------------------------------- ### Run Sample Application Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/AGENTS.md Command to execute the console sample project using the .NET 9.0 framework. ```bash dotnet run --configuration Release -f net9.0 \ --project ./sample/AspectCore.Extensions.DependencyInjection.ConsoleSample/AspectCore.Extensions.DependencyInjection.ConsoleSample.csproj ``` -------------------------------- ### Restore, compile, and test the solution Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/docs/en/development/building.md Execute standard .NET CLI commands from the repository root to prepare and validate the entire solution. ```bash # Restore NuGet dependencies dotnet restore AspectCore-Framework.sln # Compile (Release, consistent with CI) dotnet build AspectCore-Framework.sln -c Release # Run all tests dotnet test AspectCore-Framework.sln ``` -------------------------------- ### Build and Format Commands Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/AGENTS.md Commands for building the solution or individual projects and verifying code formatting. ```bash # Whole solution dotnet build AspectCore-Framework.sln --configuration Release # Per-project (matches CI behavior) for project in $(find ./src -name "*.csproj"); do dotnet build --configuration Release "$project" done # Build with explicit version (CI release flow) dotnet build --configuration Release ./src/AspectCore.Core/AspectCore.Core.csproj -p:Version=3.0.0-rc.1 # Format check (PR CI gate — currently warns, does not fail) dotnet format AspectCore-Framework.sln --verify-no-changes # Auto-format locally before pushing dotnet format AspectCore-Framework.sln ``` -------------------------------- ### Run full test suite Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/docs/en/testing/running-tests.md Executes all tests within the solution. Use -c Release to match CI behavior. ```bash dotnet test AspectCore-Framework.sln ``` -------------------------------- ### Build and test locally Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/docs/en/development/contributing.md Commands to compile the solution or run specific test projects before submitting changes. ```bash # Solution scope dotnet build AspectCore-Framework.sln -c Release dotnet test AspectCore-Framework.sln # Or narrow it to the scope of the change dotnet test tests/AspectCore.Core.Tests/AspectCore.Core.Tests.csproj ``` -------------------------------- ### Create a new benchmark class Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/benchmarks/README.md Use this template to define new benchmarks, inheriting from ProxyBenchmarkBase and applying necessary BenchmarkDotNet attributes. ```csharp using BenchmarkDotNet.Attributes; namespace AspectCore.Benchmarks; [MemoryDiagnoser] [BenchmarkCategory("MyCategory")] public class MyNewBenchmarks : ProxyBenchmarkBase { // Setup proxies in override Setup() [Benchmark(Baseline = true, Description = "Direct call")] public int Direct() => /* ... */; [Benchmark(Description = "DynamicProxy")] public int DynamicProxy() => /* ... */; [Benchmark(Description = "SourceGenerator")] public int SourceGen() => /* ... */; } ``` -------------------------------- ### Run Quick Mode Benchmarks Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/benchmarks/README.md Executes benchmarks with fewer iterations for faster CI or local iteration cycles. ```bash # Quick run (ShortRunJob - fewer iterations, less accurate) dotnet run --project benchmarks/AspectCore.Benchmarks/ -c Release -- --quick # Quick with filter dotnet run --project benchmarks/AspectCore.Benchmarks/ -c Release -- --quick --filter "*MSDI*" ``` -------------------------------- ### Run Benchmarks Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/AGENTS.md Command to execute the benchmark project for performance testing. ```bash dotnet run --configuration Release -f net9.0 \ --project ./benchmark/AspectCore.Core.Benchmark/AspectCore.Core.Benchmark.csproj ``` -------------------------------- ### Build and Test Specific Projects Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/docs/en/development/building.md Use these commands to build or test individual project files, filter test execution, or restrict testing to a specific target framework. ```bash # Build only the core package dotnet build src/AspectCore.Core/AspectCore.Core.csproj -c Release # Test only the core unit-test project dotnet test tests/AspectCore.Core.Tests/AspectCore.Core.Tests.csproj # Run only the dual-engine parity (EngineParity) cases dotnet test tests/AspectCore.Core.Tests/AspectCore.Core.Tests.csproj \ --filter "FullyQualifiedName~EngineParity" # Test on a single target framework to shorten the feedback loop dotnet test tests/AspectCore.Core.Tests/AspectCore.Core.Tests.csproj -f net8.0 ``` -------------------------------- ### Configure DI container for console applications Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/docs/en/getting-started/quick-start.md Use BuildDynamicProxyProvider to resolve services with woven proxies. ```csharp using AspectCore.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection; var services = new ServiceCollection(); services.AddTransient(); services.ConfigureDynamicProxy(); var provider = services.BuildDynamicProxyProvider(); provider.GetRequiredService().Call(); ``` -------------------------------- ### Configure DI container for ASP.NET Core Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/docs/en/getting-started/quick-start.md Attach the DynamicProxyServiceProviderFactory to the host builder. ```csharp using AspectCore.Extensions.DependencyInjection; Host.CreateDefaultBuilder(args) .UseServiceProviderFactory(new DynamicProxyServiceProviderFactory()) .ConfigureWebHostDefaults(webBuilder => webBuilder.UseStartup()); ``` -------------------------------- ### Configure Generic Host with AspectCore Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/docs/en/guide/third-party-containers.md Integrates AspectCore into the .NET Generic Host using UseServiceContext or UseDynamicProxy. ```csharp using AspectCore.DependencyInjection; using AspectCore.Extensions.Hosting; using Microsoft.Extensions.Hosting; hostBuilder.UseServiceContext(container => { container.AddType(); container.Configure(config => { config.Interceptors.AddDelegate(async (ctx, next) => { await next(ctx); ctx.ReturnValue = "proxy"; }); }); }); ``` ```csharp using AspectCore.Configuration; using AspectCore.Extensions.Hosting; using Microsoft.Extensions.DependencyInjection; hostBuilder .UseDynamicProxy() .ConfigureDynamicProxy((services, config) => { config.Interceptors.AddTyped(); }); ``` -------------------------------- ### Benchmark project structure Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/benchmarks/README.md Overview of the directory layout and key files for the benchmark suite. ```text benchmarks/ AspectCore.Benchmarks/ Program.cs # Entry point + baseline export/compare BenchmarkConfig.cs # Default + Quick configurations Services.cs # Test services and interceptors Benchmarks.cs # Core benchmarks (Sync, Async, Property, Generic, Interface, Creation) MsdiIntegrationBenchmarks.cs # MSDI DI integration benchmarks PipelineBenchmarks.cs # Multi-interceptor chain benchmarks ColdStartBenchmarks.cs # Cold start / first call benchmarks run-benchmarks.sh # Full benchmark runner script ci-benchmark.sh # CI regression detection script results/ # Output directory (gitignored) baseline.json # Saved baseline for comparison / # Full run results ci-/ # CI run results README.md # This file ``` -------------------------------- ### Execute CI Benchmarks Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/benchmarks/README.md Runs the CI benchmark script which builds in Release mode and performs a short run. ```bash ./benchmarks/ci-benchmark.sh ``` -------------------------------- ### Resolve services from IServiceResolver Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/docs/en/guide/dependency-injection.md Shows how to build the resolver and retrieve services using various resolution methods. ```csharp // build the resolver IServiceResolver resolver = services.Build(); // resolve a single service ISampleService sampleService = resolver.Resolve(); // resolve a single service, throwing if not registered ISampleService required = resolver.ResolveRequired(); // resolve a collection of services, returning an empty collection if not registered IEnumerable many = resolver.ResolveMany(); ``` -------------------------------- ### Configure LightInject with AspectCore Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/docs/en/guide/third-party-containers.md Integrates AspectCore into a LightInject ServiceContainer using RegisterDynamicProxy. ```csharp using AspectCore.Configuration; using AspectCore.Extensions.LightInject; using LightInject; var container = new ServiceContainer().RegisterDynamicProxy(config => { config.Interceptors.AddDelegate( next => ctx => next(ctx), Predicates.ForNameSpace("Your.Namespace")); }); ``` -------------------------------- ### Register services in IServiceContext Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/docs/en/guide/dependency-injection.md Demonstrates registering services by type, instance, or delegate factory using the IServiceContext interface. ```csharp using AspectCore.DependencyInjection; IServiceContext services = new ServiceContext(); // register by type services.AddType(); // register by instance (the lifetime is singleton) services.AddInstance(new TaskService()); // register by delegate factory (the delegate parameter is IServiceResolver) services.AddDelegate(resolver => new TaskService()); ``` -------------------------------- ### Register Services with MSDI Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/docs/guide/castle-migration/migration-guide.md Shows the direct equivalent of Castle Windsor registrations using Microsoft Dependency Injection (MSDI). ```csharp // MSDI lifetimes (direct equivalent) services.AddTransient(); services.AddSingleton(); services.AddScoped(); ``` -------------------------------- ### Execute Benchmarks via Shell Script Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/benchmarks/README.md Uses the provided shell script for simplified benchmark execution and help access. ```bash # Full run ./benchmarks/run-benchmarks.sh # Quick + filter ./benchmarks/run-benchmarks.sh "*ColdStart*" --quick # Show help ./benchmarks/run-benchmarks.sh --help ``` -------------------------------- ### Pack NuGet Packages Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/AGENTS.md Commands to pack projects into NuGet packages for distribution, including source and symbols. ```bash # Pack all src projects (CI build flow, includes source/symbols) for project in $(find ./src -name "*.csproj"); do dotnet pack --configuration Release --no-build "$project" \ -p:PackageVersion=3.0.0-rc.1 --include-source --output ./artifacts/packages done # Pack single project dotnet pack --configuration Release --no-build \ ./src/AspectCore.Core/AspectCore.Core.csproj \ -p:PackageVersion=3.0.0-rc.1 --output ./artifacts/packages ``` -------------------------------- ### Run Full Accuracy Benchmarks Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/benchmarks/README.md Executes the full benchmark suite or specific categories using dotnet run. ```bash # All benchmarks dotnet run --project benchmarks/AspectCore.Benchmarks/ -c Release # Specific category dotnet run --project benchmarks/AspectCore.Benchmarks/ -c Release -- --filter "*Pipeline*" # Multiple categories dotnet run --project benchmarks/AspectCore.Benchmarks/ -c Release -- --filter "*Sync*|*Async*" ``` -------------------------------- ### Equality Semantics Comparison Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/docs/en/architecture/record-support.md Demonstrates the difference in equality behavior between the Source Generator and DynamicProxy engines when comparing proxy instances. ```csharp // Source Generator engine: value equality proxyA.Equals(proxyB) // true (when all property values are equal) // DynamicProxy engine: reference equality proxyA.Equals(proxyB) // false (always reference comparison) ``` -------------------------------- ### Run AspectCore Benchmarks Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/benchmarks/README.md Commands to execute the benchmark suite in different modes or filter by specific categories. ```bash # Run all benchmarks (full accuracy) ./benchmarks/run-benchmarks.sh # Run with quick mode (CI-friendly, less accurate) ./benchmarks/run-benchmarks.sh --quick # Run a specific category ./benchmarks/run-benchmarks.sh "*Sync*" # List all available benchmarks dotnet run --project benchmarks/AspectCore.Benchmarks/ -c Release -- --list flat ``` -------------------------------- ### Register Services with Castle Windsor Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/docs/guide/castle-migration/migration-guide.md Demonstrates registering services with specific lifestyles in a Castle Windsor container. ```csharp // Castle Windsor lifestyles container.Register( Component.For().ImplementedBy().LifestyleTransient(), Component.For().ImplementedBy().LifestyleSingleton(), Component.For().ImplementedBy().LifestyleScoped() ); ``` -------------------------------- ### Configure DynamicProxyEngine Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/docs/en/architecture/engine-comparison.md Sets the proxy engine strategy and fallback behavior using the ConfigureDynamicProxyEngine method. ```csharp services.ConfigureDynamicProxyEngine(o => { o.Engine = ProxyEngine.Auto; o.AllowRuntimeFallback = true; // whether to fall back to DynamicProxy when the generated proxy is missing o.Strict = false; // strict mode: throw when the generated proxy is missing }); ``` -------------------------------- ### Run single test project Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/docs/en/testing/running-tests.md Executes tests for a specific project file. ```bash # Core unit tests dotnet test tests/AspectCore.Core.Tests/AspectCore.Core.Tests.csproj # End-to-end tests dotnet test tests/AspectCore.E2E.Tests/AspectCore.E2E.Tests.csproj # A particular container integration test dotnet test tests/AspectCore.Extensions.Autofac.Test/AspectCore.Extensions.Autofac.Test.csproj ``` -------------------------------- ### Compare Against Baseline Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/benchmarks/README.md Compares current results against the exported baseline to detect performance regressions. ```bash dotnet run --project benchmarks/AspectCore.Benchmarks/ -c Release -- --compare-baseline ``` -------------------------------- ### Invoke Constructors with ConstructorReflector Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/docs/en/guide/reflection-extensions.md Create instances using a ConstructorReflector obtained from ConstructorInfo. ```csharp var constructor = typeof(ConstructorFakes).GetTypeInfo().GetConstructor(new Type[0]); var reflector = constructor.GetReflector(); var instance = (ConstructorFakes)reflector.Invoke(); // parameterless constructor ``` -------------------------------- ### Build Service Provider Manually Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/docs/en/guide/dependency-injection.md Directly build the service provider for console applications or testing scenarios. ```csharp // directly obtain a ServiceProvider with dynamic proxying enabled var provider = services.BuildDynamicProxyProvider(); // or bridge IServiceCollection to the built-in ServiceContext and then build var provider2 = services.BuildServiceContextProvider(); ``` -------------------------------- ### Implement constructor and property injection Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/docs/en/guide/dependency-injection.md Uses constructor injection for dependencies and the [FromServiceContext] attribute for automatic property injection. ```csharp using AspectCore.DependencyInjection; public class SampleService : ISampleService { private readonly ISampleRepository _repository; private readonly ILogger _logger; // constructor injection public SampleService(ISampleRepository repository, ILogger logger) { _repository = repository; _logger = logger; } } public class SampleRepository : ISampleRepository { // property injection: a settable property annotated with [FromServiceContext] is injected automatically [FromServiceContext] public ILogger Logger { get; set; } ``` -------------------------------- ### Verify and fix code formatting Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/docs/en/development/contributing.md Use dotnet format to check for or automatically resolve code style issues. ```bash dotnet format AspectCore-Framework.sln --verify-no-changes # If there are formatting issues, run dotnet format to fix them automatically dotnet format AspectCore-Framework.sln ``` -------------------------------- ### Implement Castle IInterceptor Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/docs/guide/castle-migration/migration-guide.md Standard synchronous interceptor implementation using Castle DynamicProxy. ```csharp using Castle.DynamicProxy; public class LoggingInterceptor : IInterceptor { public void Intercept(IInvocation invocation) { Console.WriteLine($"Before: {invocation.Method.Name}"); invocation.Proceed(); Console.WriteLine($"After: {invocation.Method.Name}, returned: {invocation.ReturnValue}"); } } ``` -------------------------------- ### Migrate Interceptor Implementation Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/docs/guide/castle-migration/migration-guide.md Compares the implementation of a timing interceptor between Castle Windsor and AspectCore. ```csharp // Before (Castle) public class TimingInterceptor : IInterceptor { public void Intercept(IInvocation invocation) { var sw = Stopwatch.StartNew(); invocation.Proceed(); sw.Stop(); Console.WriteLine($"{invocation.Method.Name} took {sw.ElapsedMilliseconds}ms"); } } // After (AspectCore) public class TimingInterceptor : AbstractInterceptorAttribute { public override async Task Invoke(AspectContext context, AspectDelegate next) { var sw = Stopwatch.StartNew(); await next(context); sw.Stop(); Console.WriteLine($"{context.ServiceMethod.Name} took {sw.ElapsedMilliseconds}ms"); } } ``` -------------------------------- ### Configure CI Regression Detection Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/benchmarks/README.md Commands to generate a baseline file and commit it to version control for regression tracking. ```bash # 1. Create baseline (one-time or per-release) dotnet run --project benchmarks/AspectCore.Benchmarks/ -c Release -- --export-baseline # 2. Commit baseline.json to version control git add benchmarks/results/baseline.json # 3. In CI pipeline, run: ./benchmarks/ci-benchmark.sh ``` -------------------------------- ### Export Performance Baseline Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/benchmarks/README.md Saves current benchmark results to a JSON file for future performance tracking. ```bash dotnet run --project benchmarks/AspectCore.Benchmarks/ -c Release -- --export-baseline ``` -------------------------------- ### Configure Castle Windsor with AspectCore Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/docs/en/guide/third-party-containers.md Registers the AspectCore facility in a Windsor container, with options for custom interceptors or default configuration. ```csharp using AspectCore.Configuration; using AspectCore.Extensions.Windsor; using Castle.Windsor; var container = new WindsorContainer().AddAspectCoreFacility(config => { config.Interceptors.AddTyped(); }); ``` ```csharp var container = new WindsorContainer().AddAspectCoreFacility(); ``` -------------------------------- ### Configure Dynamic Proxy Interceptors Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/docs/en/guide/dependency-injection.md Register services and configure global interceptors on the IServiceCollection. ```csharp using AspectCore.Extensions.DependencyInjection; services.AddTransient(); services.ConfigureDynamicProxy(config => { config.Interceptors.AddTyped(); }); ``` -------------------------------- ### Implement an Async Interceptor Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/docs/en/guide/async-interception.md Create an interceptor by inheriting from AbstractInterceptorAttribute and awaiting the next delegate. ```csharp using System; using System.Threading.Tasks; using AspectCore.DynamicProxy; public class AsyncInterceptorAttribute : AbstractInterceptorAttribute { public override async Task Invoke(AspectContext context, AspectDelegate next) { Console.WriteLine("Before async call"); await next(context); Console.WriteLine("After async call"); } } ``` -------------------------------- ### Namespace Scoping Style Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/AGENTS.md Use block-scoped namespaces instead of file-scoped namespaces. ```csharp // ✅ namespace AspectCore.DynamicProxy { public interface IInterceptor { ... } } // ❌ namespace AspectCore.DynamicProxy; public interface IInterceptor { ... } ``` -------------------------------- ### Register Global Interceptor via ConfigureDynamicProxy Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/docs/en/guide/interceptor-configuration.md The entry point for global interceptor registration using the ConfigureDynamicProxy method. ```csharp using AspectCore.Configuration; using AspectCore.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection; services.ConfigureDynamicProxy(config => { config.Interceptors.AddTyped(); }); ``` -------------------------------- ### Create a feature branch Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/docs/en/development/contributing.md Use these commands to synchronize with the master branch and create a new feature branch. ```bash git fetch origin git switch -c feat/ origin/master ``` -------------------------------- ### Bind Entire Sections with [ConfigurationBinding] Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/docs/en/guide/configuration-injection.md Bind an entire configuration section to a complex type field using the [ConfigurationBinding] attribute. ```csharp using AspectCore.Extensions.Configuration; public class Config { public string Name { get; set; } public int Age { get; set; } } public class BindConfigService { [ConfigurationBinding("creator")] private readonly Config _config = default!; public override string ToString() => $"{_config.Name}-{_config.Age}"; } ``` -------------------------------- ### Configuring global exclusions with NonAspectPredicates Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/docs/en/guide/conditional-interception.md Use NonAspectPredicates in the configuration to exclude services, namespaces, or methods in bulk using wildcards. ```csharp services.ConfigureDynamicProxy(config => { // services under the App1 namespace are not proxied config.NonAspectPredicates.AddNamespace("App1"); // services under namespaces whose last segment is App1 are not proxied config.NonAspectPredicates.AddNamespace("*.App1"); // the ICustomService interface is not proxied config.NonAspectPredicates.AddService("ICustomService"); // interfaces and classes with the suffix Service are not proxied config.NonAspectPredicates.AddService("*Service"); // methods named Query are not proxied config.NonAspectPredicates.AddMethod("Query"); // methods with the suffix Query are not proxied config.NonAspectPredicates.AddMethod("*Query"); }); ``` -------------------------------- ### Implement AspectCore AbstractInterceptorAttribute Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/docs/guide/castle-migration/migration-guide.md Asynchronous interceptor implementation using AspectCore's AbstractInterceptorAttribute. ```csharp using AspectCore.DynamicProxy; public class LoggingInterceptor : AbstractInterceptorAttribute { public override async Task Invoke(AspectContext context, AspectDelegate next) { Console.WriteLine($"Before: {context.ServiceMethod.Name}"); await next(context); Console.WriteLine($"After: {context.ServiceMethod.Name}, returned: {context.ReturnValue}"); } } ``` -------------------------------- ### Execute AspectCore tests via CLI Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/AGENTS.md Commands for running test suites, filtering specific tests, and generating coverage reports using the .NET CLI. ```bash # All test projects (CI behavior) for project in $(find ./tests -name "*.csproj"); do dotnet test --configuration Release "$project" done # Single test project dotnet test --configuration Release ./tests/AspectCore.Core.Tests/AspectCore.Core.Tests.csproj # Single target framework (tests target net10.0;net9.0;net8.0;net6.0) dotnet test --configuration Release -f net9.0 ./tests/AspectCore.Core.Tests/AspectCore.Core.Tests.csproj # Filter a single test (xUnit filter syntax) dotnet test --configuration Release ./tests/AspectCore.Core.Tests/AspectCore.Core.Tests.csproj \ --filter "FullyQualifiedName~AspectCore.Core.Tests.ProxyTests" # With coverage (matches .github/scripts/check-coverage.sh) dotnet test ./tests/AspectCore.Core.Tests/AspectCore.Core.Tests.csproj \ --configuration Release -f net9.0 \ /p:CollectCoverage=true /p:CoverletOutputFormat=cobertura \ /p:CoverletOutput=./TestResults/ \ "/p:Include=[AspectCore.Core]*" ``` -------------------------------- ### Register services in ASP.NET Core Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/docs/en/getting-started/quick-start.md Call ConfigureDynamicProxy within the ConfigureServices method. ```csharp public void ConfigureServices(IServiceCollection services) { services.AddTransient(); services.ConfigureDynamicProxy(); } ``` -------------------------------- ### Match by Service Name with Predicates.ForService Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/docs/en/guide/conditional-interception.md Matches services based on their type name, stripping generic markers. ```csharp // services whose type name ends with Service config.Interceptors.AddTyped(Predicates.ForService("*Service")); ``` -------------------------------- ### Autofac RegisterDynamicProxy Overloads Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/docs/en/guide/third-party-containers.md Reference for the available method signatures for registering dynamic proxies in Autofac. ```csharp // ContainerBuilder RegisterDynamicProxy(this ContainerBuilder, Action configure = null) // ContainerBuilder RegisterDynamicProxy(this ContainerBuilder, IAspectConfiguration configuration, Action configure = null) ``` -------------------------------- ### Enable Configuration Injection in ServiceContext Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/docs/en/guide/configuration-injection.md Register an IConfiguration instance and call AddConfigurationInject to enable the injection mechanism. ```csharp using AspectCore.DependencyInjection; using AspectCore.Extensions.Configuration; using Microsoft.Extensions.Configuration; var container = new ServiceContext(); container.AddInstance(configuration); container.AddConfigurationInject(); // enable configuration injection container.AddType(); var service = container.Build().Resolve(); ``` -------------------------------- ### Implement Logging Interceptor in C# Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/docs/en/guide/common-scenarios.md Uses AbstractInterceptorAttribute to log method entry, execution time, and results. Requires ILogger from the service provider. ```csharp using System; using System.Linq; using System.Threading.Tasks; using AspectCore.DynamicProxy; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; public class LoggingInterceptorAttribute : AbstractInterceptorAttribute { public override async Task Invoke(AspectContext context, AspectDelegate next) { var logger = context.ServiceProvider.GetService>(); var methodName = $"{context.ServiceMethod.DeclaringType.Name}.{context.ServiceMethod.Name}"; var parameters = string.Join(", ", context.Parameters.Select(p => p?.ToString() ?? "null")); logger.LogInformation("[START] {Method}({Params})", methodName, parameters); var stopwatch = System.Diagnostics.Stopwatch.StartNew(); try { await next(context); stopwatch.Stop(); var result = await context.UnwrapAsyncReturnValue(); logger.LogInformation("[END] {Method} in {Elapsed}ms. Result: {Result}", methodName, stopwatch.ElapsedMilliseconds, result); } catch (Exception ex) { stopwatch.Stop(); logger.LogError(ex, "[ERROR] {Method} failed after {Elapsed}ms", methodName, stopwatch.ElapsedMilliseconds); throw; } } } ``` -------------------------------- ### Castle IAsyncInterceptor implementation Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/docs/guide/castle-migration/migration-guide.md Castle requires a separate interface for handling asynchronous interception. ```csharp // Castle: async interception requires a wrapper public class AsyncLoggingInterceptor : IAsyncInterceptor { public void InterceptSynchronous(IInvocation invocation) { ... } public void InterceptAsynchronous(IInvocation invocation) { ... } public void InterceptAsynchronous(IInvocation invocation) { ... } } ``` -------------------------------- ### Implement Castle IInterceptorSelector Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/docs/guide/castle-migration/migration-guide.md Define custom selection logic by implementing IInterceptorSelector and passing it to ProxyGenerationOptions. ```csharp // Castle: using IInterceptorSelector public class MySelector : IInterceptorSelector { public IInterceptor[] SelectInterceptors(Type type, MethodInfo method, IInterceptor[] interceptors) { if (method.Name.StartsWith("Get")) return interceptors.Where(i => i is CachingInterceptor).ToArray(); return interceptors; } } // Usage var options = new ProxyGenerationOptions { Selector = new MySelector() }; var proxy = generator.CreateInterfaceProxyWithTarget(target, options, interceptors); ``` -------------------------------- ### Configure AspectCore Interceptors Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/docs/guide/castle-migration/migration-guide.md Use global predicates for dynamic configuration or attributes for declarative interception control. ```csharp // Option 1: Global predicate-based configuration services.ConfigureDynamicProxy(config => { // Apply to methods starting with "Get" config.Interceptors.AddTyped( method => method.Name.StartsWith("Get")); // Apply to all services matching a pattern config.Interceptors.AddTyped( Predicates.ForService("*Service*")); // Exclude specific methods/services config.NonAspectPredicates.Add( method => method.Name == "ToString"); }); // Option 2: Attribute-based (on interface or class) public interface IMyService { [CachingInterceptor] string GetValue(string key); string SetValue(string key, string value); // not intercepted } // Option 3: Exclude from interception [NonAspect] public interface INotIntercepted { } ``` -------------------------------- ### Match by Type Implementation with Predicates.Implement Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/docs/en/guide/conditional-interception.md Targets types that implement a specific interface or inherit from a base class. The target type must not be sealed. ```csharp // all types that implement IRepository config.Interceptors.AddTyped(Predicates.Implement(typeof(IRepository))); ``` -------------------------------- ### Specify target framework Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/docs/en/testing/running-tests.md Limits test execution to a single framework using the -f flag. ```bash # net8.0 only (Core.Tests targets net10.0;net9.0;net8.0;net6.0) dotnet test tests/AspectCore.Core.Tests/AspectCore.Core.Tests.csproj -f net8.0 # net9.0 only dotnet test tests/AspectCore.E2E.Tests/AspectCore.E2E.Tests.csproj -f net9.0 ``` -------------------------------- ### Implement a Caching Interceptor in C# Source: https://github.com/dotnetcore/aspectcore-framework/blob/master/docs/en/guide/common-scenarios.md Uses IMemoryCache to store and retrieve method results. Requires re-wrapping return values for asynchronous methods. ```csharp using System; using System.Linq; using System.Threading.Tasks; using AspectCore.DynamicProxy; using Microsoft.Extensions.Caching.Memory; public class CacheInterceptorAttribute : AbstractInterceptorAttribute { private readonly int _durationSeconds; public CacheInterceptorAttribute(int durationSeconds = 60) => _durationSeconds = durationSeconds; public override async Task Invoke(AspectContext context, AspectDelegate next) { var cache = context.ServiceProvider.GetService(typeof(IMemoryCache)) as IMemoryCache; var cacheKey = GetCacheKey(context); if (cache.TryGetValue(cacheKey, out var cached)) { // cache hit, short-circuit the original method; async methods must re-wrap into Task context.ReturnValue = Task.FromResult(cached); return; } await next(context); var result = await context.UnwrapAsyncReturnValue(); cache.Set(cacheKey, result, TimeSpan.FromSeconds(_durationSeconds)); } private static string GetCacheKey(AspectContext context) => $"{context.ServiceMethod.DeclaringType.Name}.{context.ServiceMethod.Name}_{string.Join("_", context.Parameters)}"; } ```