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
<PackageReference Include="Galosys.Foundation.Castle.Core" Version="26.7.31.1" />
<PackageVersion Include="Galosys.Foundation.Castle.Core" Version="26.7.31.1" />
<PackageReference Include="Galosys.Foundation.Castle.Core" />
paket add Galosys.Foundation.Castle.Core --version 26.7.31.1
#r "nuget: Galosys.Foundation.Castle.Core, 26.7.31.1"
#:package Galosys.Foundation.Castle.Core@26.7.31.1
#addin nuget:?package=Galosys.Foundation.Castle.Core&version=26.7.31.1
#tool nuget:?package=Galosys.Foundation.Castle.Core&version=26.7.31.1
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 方法 |
| 性能 | 略快 | 略慢 |
类代理限制:非 virtual 的 public 方法静默跳过代理(不拦截、无提示)。启动时 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必须在所有服务注册之后调用(替换式注册) - ValidateScopes:
UseCastleCoreServiceProvider()默认启用;若代理的 Singleton 服务依赖 Scoped 构造参数,会抛出InvalidOperationException,包含具体提示 - 拦截器嵌套:拦截器内不要创建新代理
- AOT:Castle.Core 基于 Emit,Native AOT 不可用
依赖
- Castle.Core 5.1.1
- Polly.Core
- Galosys.Foundation.Core
| Product | Versions 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. |
-
net10.0
- castle.core (>= 5.1.1)
- Galosys.Foundation.Actuator (>= 26.7.31.1)
- Galosys.Foundation.Core (>= 26.7.31.1)
- polly.core (>= 8.4.2)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.