Examples

Get going with comprehensive examples that show you the power of aspect oriented programming with modern .NET 8.0/6.0.

Download Now

Getting Started with Aspekt

Aspekt is now modernized for .NET 8.0, .NET 6.0, and .NET Standard 2.1, bringing you the latest performance improvements and modern C# features.

Installation

Install Aspekt via NuGet:

dotnet add package Aspekt

Basic Logging Aspect

Create your first aspect to add logging to any method:

using Aspekt;

public class LoggingAspect : Aspect
{
    public override void OnEntry(MethodArguments args)
    {
        Console.WriteLine($"Entering: {args.FullName}");
        if (args.Arguments.Count > 0)
        {
            Console.WriteLine($"  Parameters: [{string.Join(", ", args.Arguments.Values)}]");
        }
    }

    public override void OnExit(MethodArguments args)
    {
        Console.WriteLine($"Exiting: {args.FullName}");
    }

    public override void OnException(MethodArguments args, Exception e)
    {
        Console.WriteLine($"Exception in {args.FullName}: {e.Message}");
    }
}

// Apply the aspect to your methods
public class Calculator
{
    [LoggingAspect]
    public int Add(int a, int b)
    {
        return a + b;
    }
}

Performance Monitoring

Track execution time of your methods:

using Aspekt;
using System.Diagnostics;

public class PerformanceMonitoringAspect : Aspect
{
    private Stopwatch? _stopwatch;

    public override void OnEntry(MethodArguments args)
    {
        _stopwatch = Stopwatch.StartNew();
    }

    public override void OnExit(MethodArguments args)
    {
        _stopwatch?.Stop();
        Console.WriteLine($"{args.Name} executed in {_stopwatch?.ElapsedMilliseconds}ms");
    }
}

public class DataProcessor
{
    [PerformanceMonitoring]
    public void ProcessLargeDataSet(int[] data)
    {
        // Your processing logic here
        Array.Sort(data);
    }
}

Contract Programming - Input Validation

Use built-in contract aspects to enforce preconditions:

using Aspekt.Contracts;

public class UserService
{
    // Validate that age parameter is greater than 0
    [RequiresArgument("age", typeof(int), Contract.Comparison.GreaterThan, 0)]
    public void RegisterUser(string name, int age)
    {
        // Registration logic - age is guaranteed to be > 0
        Console.WriteLine($"Registering user: {name}, age: {age}");
    }

    // Validate that email is not null or empty
    [RequiresArgument("email", typeof(string), Contract.Constraint.NotNullOrEmpty)]
    public void SendEmail(string email, string message)
    {
        // Email logic - email is guaranteed to be valid
        Console.WriteLine($"Sending email to: {email}");
    }
}

Return Value Interception

Modify or validate return values using IAspectExitHandler<T>:

using Aspekt;

public class CacheAspect : Aspect, IAspectExitHandler<string>
{
    private static readonly Dictionary<string, string> Cache = new();

    public string OnExit(MethodArguments args, string result)
    {
        // Cache the result
        var key = $"{args.FullName}_{string.Join("_", args.Arguments.Values)}";
        Cache[key] = result;
        Console.WriteLine($"Cached result for {args.Name}");
        return result;
    }
}

public class DataService
{
    [CacheAspect]
    public string GetUserData(int userId)
    {
        // Expensive database call
        return $"User data for {userId}";
    }
}

Modern Async/Await Support

Aspekt supports modern async patterns:

using Aspekt;

public class AsyncLoggingAspect : Aspect
{
    public override async ValueTask OnEntryAsync(MethodArguments args, 
        CancellationToken cancellationToken = default)
    {
        await Console.Out.WriteLineAsync($"Async entering: {args.FullName}");
    }

    public override async ValueTask OnExitAsync(MethodArguments args, 
        CancellationToken cancellationToken = default)
    {
        await Console.Out.WriteLineAsync($"Async exiting: {args.FullName}");
    }
}

public class AsyncService
{
    [AsyncLoggingAspect]
    public async Task<string> FetchDataAsync()
    {
        await Task.Delay(100);
        return "Data fetched";
    }
}

Exception Handling and Recovery

Implement sophisticated exception handling:

using Aspekt;

public class RetryAspect : Aspect
{
    private readonly int _maxRetries;
    
    public RetryAspect(int maxRetries = 3)
    {
        _maxRetries = maxRetries;
    }

    public override void OnException(MethodArguments args, Exception e)
    {
        Console.WriteLine($"Exception caught in {args.Name}: {e.Message}");
        Console.WriteLine($"Retry logic could be implemented here");
        // In real implementation, you would coordinate with the weaver
        // to retry the method execution
    }
}

public class NetworkService
{
    [RetryAspect(maxRetries: 3)]
    public string FetchFromRemoteServer(string url)
    {
        // Network call that might fail
        throw new TimeoutException("Server timeout");
    }
}

Multiple Aspects

Combine multiple aspects on a single method:

using Aspekt;
using Aspekt.Contracts;

public class BusinessService
{
    [PerformanceMonitoring]
    [LoggingAspect]
    [RequiresArgument("amount", typeof(decimal), Contract.Comparison.GreaterThan, 0)]
    public decimal ProcessPayment(decimal amount, string currency)
    {
        // Payment processing logic
        // Automatically logged, timed, and validated!
        return amount * 1.05m; // Add processing fee
    }
}

What’s New in Aspekt