< Summary

Information
Class: NexusLabs.Needlr.InterceptAttribute
Assembly: NexusLabs.Needlr
File(s): /home/runner/work/needlr/needlr/src/NexusLabs.Needlr/InterceptAttribute.cs
Line coverage
100%
Covered lines: 5
Uncovered lines: 0
Coverable lines: 5
Total lines: 137
Line coverage: 100%
Branch coverage
100%
Covered branches: 2
Total branches: 2
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%22100%
get_InterceptorType()100%11100%
get_Order()100%11100%

File(s)

/home/runner/work/needlr/needlr/src/NexusLabs.Needlr/InterceptAttribute.cs

#LineLine coverage
 1namespace NexusLabs.Needlr;
 2
 3/// <summary>
 4/// Applies an interceptor to a class or method. When discovered by Needlr's
 5/// source generator, a proxy class is generated that routes method calls
 6/// through the specified interceptor(s).
 7/// </summary>
 8/// <remarks>
 9/// <para>
 10/// This attribute can be applied at the class level (intercepts all methods)
 11/// or at the method level (intercepts only that method).
 12/// </para>
 13/// <para>
 14/// The interceptor type must implement <see cref="IMethodInterceptor"/> and
 15/// will be resolved from the DI container, allowing it to have dependencies.
 16/// </para>
 17/// <para>
 18/// When multiple interceptors are applied, use the <see cref="Order"/> property
 19/// to control execution order. Lower values execute first (outermost in the chain).
 20/// </para>
 21/// <para>
 22/// <strong>Note:</strong> Interceptors are only supported with source generation.
 23/// They are not available when using reflection-based registration.
 24/// </para>
 25/// </remarks>
 26/// <example>
 27/// <code>
 28/// // Class-level interception (all methods)
 29/// [Intercept(typeof(LoggingInterceptor))]
 30/// [Scoped]
 31/// public class OrderService : IOrderService
 32/// {
 33///     public Task&lt;Order&gt; GetOrderAsync(int id) => ...;
 34///     public Task CreateOrderAsync(Order order) => ...;
 35/// }
 36///
 37/// // Method-level interception
 38/// [Scoped]
 39/// public class ProductService : IProductService
 40/// {
 41///     [Intercept(typeof(CachingInterceptor))]
 42///     public Task&lt;Product&gt; GetProductAsync(int id) => ...;
 43///
 44///     // This method is NOT intercepted
 45///     public Task UpdateProductAsync(Product product) => ...;
 46/// }
 47///
 48/// // Multiple interceptors with ordering
 49/// [Intercept(typeof(LoggingInterceptor), Order = 1)]
 50/// [Intercept(typeof(TimingInterceptor), Order = 2)]
 51/// [Scoped]
 52/// public class ReportService : IReportService { }
 53/// </code>
 54/// </example>
 55[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = false, AllowMultiple = true)]
 56public sealed class InterceptAttribute : Attribute
 57{
 58    /// <summary>
 59    /// Initializes a new instance of the <see cref="InterceptAttribute"/> class.
 60    /// </summary>
 61    /// <param name="interceptorType">
 62    /// The type of the interceptor. Must implement <see cref="IMethodInterceptor"/>.
 63    /// </param>
 64    /// <exception cref="ArgumentNullException">
 65    /// Thrown when <paramref name="interceptorType"/> is null.
 66    /// </exception>
 567    public InterceptAttribute(Type interceptorType)
 68    {
 569        InterceptorType = interceptorType ?? throw new ArgumentNullException(nameof(interceptorType));
 470    }
 71
 72    /// <summary>
 73    /// Gets the type of the interceptor to apply.
 74    /// </summary>
 175    public Type InterceptorType { get; }
 76
 77    /// <summary>
 78    /// Gets or sets the order in which this interceptor executes relative to
 79    /// other interceptors on the same target. Lower values execute first
 80    /// (outermost in the interceptor chain). Default is 0.
 81    /// </summary>
 82    /// <remarks>
 83    /// <para>
 84    /// Example with Order values:
 85    /// <list type="bullet">
 86    /// <item>Order = 1: LoggingInterceptor (executes first, wraps everything)</item>
 87    /// <item>Order = 2: CachingInterceptor (executes second)</item>
 88    /// <item>Order = 3: ValidationInterceptor (executes last, closest to actual method)</item>
 89    /// </list>
 90    /// </para>
 91    /// </remarks>
 392    public int Order { get; set; } = 0;
 93}
 94
 95/// <summary>
 96/// Applies an interceptor to a class or method. Generic version that provides
 97/// compile-time type safety for the interceptor type.
 98/// </summary>
 99/// <typeparam name="TInterceptor">
 100/// The type of the interceptor. Must implement <see cref="IMethodInterceptor"/>.
 101/// </typeparam>
 102/// <remarks>
 103/// <para>
 104/// This is the preferred form when the interceptor type is known at compile time.
 105/// For dynamic scenarios, use the non-generic <see cref="InterceptAttribute"/>.
 106/// </para>
 107/// <para>
 108/// See <see cref="InterceptAttribute"/> for full documentation and examples.
 109/// </para>
 110/// </remarks>
 111/// <example>
 112/// <code>
 113/// [Intercept&lt;LoggingInterceptor&gt;(Order = 1)]
 114/// [Intercept&lt;CachingInterceptor&gt;(Order = 2)]
 115/// [Scoped]
 116/// public class OrderService : IOrderService
 117/// {
 118///     public Task&lt;Order&gt; GetOrderAsync(int id) => ...;
 119/// }
 120/// </code>
 121/// </example>
 122[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = false, AllowMultiple = true)]
 123public sealed class InterceptAttribute<TInterceptor> : Attribute
 124    where TInterceptor : class, IMethodInterceptor
 125{
 126    /// <summary>
 127    /// Gets the type of the interceptor to apply.
 128    /// </summary>
 129    public Type InterceptorType => typeof(TInterceptor);
 130
 131    /// <summary>
 132    /// Gets or sets the order in which this interceptor executes relative to
 133    /// other interceptors on the same target. Lower values execute first
 134    /// (outermost in the interceptor chain). Default is 0.
 135    /// </summary>
 136    public int Order { get; set; } = 0;
 137}