Galosys.Foundation.Castle.Core 26.7.31.1

dotnet add package Galosys.Foundation.Castle.Core --version 26.7.31.1
                    
NuGet\Install-Package Galosys.Foundation.Castle.Core -Version 26.7.31.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Galosys.Foundation.Castle.Core" Version="26.7.31.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Galosys.Foundation.Castle.Core" Version="26.7.31.1" />
                    
Directory.Packages.props
<PackageReference Include="Galosys.Foundation.Castle.Core" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Galosys.Foundation.Castle.Core --version 26.7.31.1
                    
#r "nuget: Galosys.Foundation.Castle.Core, 26.7.31.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Galosys.Foundation.Castle.Core@26.7.31.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Galosys.Foundation.Castle.Core&version=26.7.31.1
                    
Install as a Cake Addin
#tool nuget:?package=Galosys.Foundation.Castle.Core&version=26.7.31.1
                    
Install as a Cake Tool

Galosys.Foundation.Castle.Core

成熟度: 🟢 稳定 — 生产可用,测试充分,活跃维护

基于 Castle.DynamicProxy 的 AOP 拦截模块。核心设计理念:

  • 原生 Castle 集成 — 直接使用 Castle 的 IInterceptor / IInvocation / ProxyGenerator
  • 继承式拦截 — 拦截器特性继承 InterceptorAttribute 覆写 InterceptAsync,无需独立 Handler 类
  • 单一适配器InterceptorAdapter 一个 IInterceptor 实现,自动发现方法上的所有 InterceptorAttribute 子类并执行链式分派

架构概览

用户代码 → [MyAttribute] 标记 → DI 自动代理注册 → Castle 生成代理 → 方法调用 → InterceptorAdapter.Intercept()GetCustomAttributes<InterceptorAttribute>()MyAttribute.InterceptAsync()invocation.Proceed() → 业务方法

┌─ Service 层 ─────────────────────────────────────────────┐
│  [Transactional]                                          │
│  public class OrderService {                              │
│      public virtual async Task CreateAsync() { ... }      │
│  }                                                         │
└──────────────────────────┬───────────────────────────────┘
                           │ DI 注入(Castle 自动代理)
                           ▼
┌─ Castle 代理 ────────────────────────────────────────────┐
│  ProxyGenerator.CreateClassProxy / CreateInterfaceProxy   │
│  → InterceptorAdapter.Intercept()                         │
│    → GetCustomAttributes<InterceptorAttribute>()          │
│    → TransactionalAttribute.InterceptAsync(invocation, sp)│
│      → invocation.ProceedAsync()                           │
└──────────────────────────────────────────────────────────┘

安装

dotnet add package Galosys.Foundation.Castle.Core

定义拦截器

继承 InterceptorAttribute 并覆写 InterceptAsync 方法:

using Castle.DynamicProxy;

public class AuditLogAttribute : InterceptorAttribute
{
    public override async ValueTask InterceptAsync(IAsyncInvocation invocation, IServiceProvider sp)
    {
        Console.WriteLine($"[Audit] 调用: {invocation.Invocation.Method.Name}");
        await invocation.ProceedAsync();
        Console.WriteLine($"[Audit] 返回: {invocation.Result}");
    }
}

public class PaymentService
{
    [AuditLog]
    public virtual async Task PayAsync(decimal amount)
    {
        await Task.CompletedTask;
    }
}

InterceptorAttribute 自动处理同步 void / Task / ValueTask / Task<T> / ValueTask<T> 所有返回类型。


内置拦截器

[Transactional] — 事务管理(Castle.DynamicProxy

参数 类型 默认值 说明
IsolationLevel IsolationLevel ReadCommitted 事务隔离级别
TransactionScopeOption TransactionScopeOption Required 事务范围选项
Timeout long (ms) 60000 超时时间(毫秒)
[Transactional]
public virtual async Task CreateOrderAsync(Order order) { }

[Transactional(IsolationLevel = IsolationLevel.Serializable, Timeout = 30000)]
public virtual void ProcessPayment(Payment payment) { }

[Retryable] — 重试策略(基于 Polly,Castle.DynamicProxy

参数 类型 默认值 说明
MaxAttempts int 3 最大尝试次数
MaxDelay int (ms) 5000 基础延迟(毫秒)
Multiplier double 2 指数退避乘数
RetryFor Type typeof(Exception) 仅对指定异常类型重试
[Retryable]
public virtual async Task<string> CallApiAsync() { }

[Retryable(MaxAttempts = 5, MaxDelay = 10000, Multiplier = 2)]
public virtual async Task<Data> FetchDataAsync() { }

[Retryable(RetryFor = typeof(HttpRequestException))]
public virtual async Task<Response> ResilientCallAsync() { }

[CatchLogging] — 异常日志记录(Castle.DynamicProxy

无配置参数。自动记录方法执行耗时。异常信息通过 ILogChannel<CatchLoggingEvent> 写入日志管道。

[CatchLogging]
public virtual async Task ExecuteAsync() { }

注册方式

方式一:自动注册(推荐)

// Program.cs
builder.Host.UseCastleCoreServiceProvider();

内部自动执行 services.ConfigureCastleDynamicProxy(),将所有标注了 InterceptorAttribute 子类的服务实现替换为 Castle 代理。

方式二:手动注册

// 需在所有服务注册完成后调用
builder.Services.ConfigureCastleDynamicProxy();

接口代理 vs 类代理

接口代理 类代理
要求 实现接口 类 + virtual 方法
示例 IService + Service class Service { virtual void X() }
虚方法 不需要 必须 virtual
拦截范围 接口定义的方法 所有 public virtual 方法
性能 略快 略慢

类代理限制:非 virtualpublic 方法静默跳过代理(不拦截、无提示)。启动时 ConfigureCastleDynamicProxy 会对非虚方法输出 Trace 警告。


异步支持

InterceptorAdapter 统一处理 5 种返回类型:

返回类型 处理方式
void 同步路径,GetAwaiter().GetResult()
Task chain().AsTask() 返回给 Castle
Task<T> WrapTaskResult<T> 提取结果
ValueTask chain() 直接作为 ReturnValue
ValueTask<T> WrapValueTaskResult<T> 提取结果

拦截器链

多个 Attribute 叠加时,按方法上的声明顺序执行(从外到内)。

// 执行顺序:1) Transactional → 2) Retryable → 3) CatchLogging
[Transactional]
[Retryable(MaxAttempts = 2)]
[CatchLogging]
public virtual async Task ComplexOperationAsync()
{
    // 业务方法在最内层执行
}

核心类参考

命名空间 说明
InterceptorAttribute Castle.DynamicProxy 拦截器基类,继承 Attribute,抽象 InterceptAsync(IAsyncInvocation, IServiceProvider)
InterceptorAdapter Castle.DynamicProxy 单一 IInterceptor 实现,自动发现方法上的 InterceptorAttribute 子类
IAsyncInvocation Castle.DynamicProxy 异步调用上下文,ProceedAsync() 调用下一管道
TransactionalAttribute Castle.DynamicProxy 事务拦截器
RetryableAttribute Castle.DynamicProxy 重试拦截器
CatchLoggingAttribute Castle.DynamicProxy 日志拦截器
CastleCoreServiceCollectionExtensions Microsoft.Extensions.DependencyInjection ConfigureCastleDynamicProxy()
CastleCoreHostBuilderExtensions Microsoft.Extensions.Hosting UseCastleCoreServiceProvider()

测试覆盖

集成测试位于 framework/test/Galosys.Foundation.Castle.Core.Tests/,涵盖:

  • ConfigureCastleDynamicProxy — ProxyGenerator 单例注册、三种注册方式的代理替换(ImplementationType / Instance / Factory)
  • 生命周期保留 — Singleton / Scoped / Transient 在代理替换后行为不变
  • 代理类型 — 接口代理(ITestService)、类代理(TestClassService)
  • 拦截器链 — 多 Attribute 叠加执行
  • 异步支持 — void / Task / Task<T> / ValueTask / ValueTask<T>
  • CastleCoreServiceProviderFactory — IHostBuilder 集成链路

运行测试:

dotnet test framework/test/Galosys.Foundation.Castle.Core.Tests/

性能基线

BenchmarkDotNet v0.13.12 / .NET 10.0.1 / RyuJIT AVX2(framework/test/Galosys.Foundation.Castle.Core.Benchmarks/

场景 Mean 相对基线
直接调用(基线) 3.6 ns 1.00x
Castle 代理 + Noop 拦截器 16.2 ns 4.50x
InterceptorAdapter 直通(无匹配) 3.8 ns 1.06x
[Transactional] 3.8 ns 1.06x
[Retryable] 7.0 ns 1.94x
[CatchLogging] 7.2 ns 2.00x

注意事项

  • 虚方法:类代理必须 virtual,否则拦截静默跳过
  • 注册顺序ConfigureCastleDynamicProxy 必须在所有服务注册之后调用(替换式注册)
  • ValidateScopesUseCastleCoreServiceProvider() 默认启用;若代理的 Singleton 服务依赖 Scoped 构造参数,会抛出 InvalidOperationException,包含具体提示
  • 拦截器嵌套:拦截器内不要创建新代理
  • AOT:Castle.Core 基于 Emit,Native AOT 不可用

依赖

  • Castle.Core 5.1.1
  • Polly.Core
  • Galosys.Foundation.Core
Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
26.7.31.1 31 7/31/2026
26.7.30.1 33 7/30/2026
26.7.29.1 38 7/29/2026
26.7.28.1 38 7/28/2026
26.7.26.2 73 7/26/2026
26.7.26.1 73 7/25/2026