Skip to content

Latest commit

 

History

History
153 lines (112 loc) · 3.79 KB

File metadata and controls

153 lines (112 loc) · 3.79 KB

BeyondNet.Aop

English | Español

BeyondNet.Aop is a high-performance Aspect-Oriented Programming (AOP) framework for .NET 10. It allows you to cleanly separate cross-cutting concerns (like logging, error handling, retries, etc.) from your core business logic using native .NET DispatchProxy with heavy caching optimizations.

Features

  • High Performance: Uses ConcurrentDictionary to cache reflection calls and dynamic expression compilation (O(1) lookups).
  • Clean Code: Strict naming conventions and semantic exceptions.
  • Native .NET: Built on top of System.Reflection.DispatchProxy without requiring complex post-compilation weaving tools.
  • Extensible: Easily plug in custom loggers or evaluation engines.
  • Observability: Built-in Serilog integration with structured logging and execution context propagation.
  • DI Integration: Seamless integration with Microsoft.Extensions.DependencyInjection.

Architecture

The framework is organized into modular packages:

BeyondNetCode.Shell.Aop              # Core abstractions (IAspect, IJoinPoint, AspectExecutor)
BeyondNetCode.Shell.Aop.Aspects      # Pre-built aspects (Retry, Logger, Advice)
BeyondNetCode.Shell.Aop.DispatchProxy # Proxy creation using DispatchProxy
BeyondNetCode.Shell.Aop.Aspects.Logger # Common.Logging integration
BeyondNetCode.Shell.Aop.Aspects.Logger.Serilog # Serilog integration with structured logging
BeyondNetCode.Shell.Aop.DI           # Dependency Injection extensions

Installation

# Core library
dotnet add package BeyondNetCode.Shell.Aop

# Pre-built aspects
dotnet add package BeyondNetCode.Shell.Aop.Aspects

# Serilog integration (recommended)
dotnet add package BeyondNetCode.Shell.Aop.Aspects.Logger.Serilog

# DI installer
dotnet add package BeyondNetCode.Shell.Aop.DI

Quick Start

Step 1: Define an Aspect Attribute

[AttributeUsage(AttributeTargets.Method)]
public class MyLogAttribute : AbstractAspectAttribute
{
    public string Message { get; set; }
}

Step 2: Implement the Aspect

public class MyLogAspect : OnMethodBoundaryAspect<MyLogAttribute>
{
    protected override void OnEntry(IJoinPoint joinPoint)
    {
        var attr = GetAttribute(joinPoint);
        Console.WriteLine($"Method {joinPoint.MethodInfo.Name}: {attr.Message}");
    }
}

Step 3: Apply to Interface Methods

public interface IMyService
{
    [MyLog(Message = "Starting operation")]
    Task<Result> DoWorkAsync();
}

Step 4: Register in DI

services.AddAopAspects(typeof(IMyService).Assembly);

Advanced Topics

Custom Pointcuts

Implement IPointCut to control when aspects are applied:

public class MyPointCut : IPointCut
{
    public bool CanApply(IJoinPoint joinPoint, Type aspectType)
    {
        // Custom logic
    }
}

Aspect Ordering

Use the Order property on attributes to control execution order:

[MyAspect(Order = 1)]
[AnotherAspect(Order = 2)]
void MyMethod() { }

Retry with Exponential Backoff

public class RetryAttribute : AbstractAspectAttribute
{
    public int MaxRetries { get; set; } = 3;
    public int BaseDelayMs { get; set; } = 1000;
}

public class RetryAspect : OnRetryAspect<RetryAttribute>
{
    protected override bool CanRetry(IJoinPoint joinPoint, Exception ex)
    {
        return GetAttribute(joinPoint) is { } attr &&
               attr.MaxRetries > 0;
    }
}

Testing

dotnet test

Contributing

See CONTRIBUTING.md for GitFlow workflow and coding standards.

Versioning

See VERSIONING.md for SemVer strategy.

License

Apache 2.0 - See LICENSE

Acknowledgments

See DISCLAIMER.md for original code authorship.