MethodInfo ProxyMethod { get; }
object ProxyTarget { get; }
MethodInfo Method { get; }
object Target { get; }
object[] Arguments { get; }
Type[] GenericArguments { get; }
object ReturnValue { get; set; }
Dictionary<string, object> Properties { get; }
}
### IInterceptor
拦截器,用来定义公用的处理逻辑,方法拦截处理方法
接口定义如下:
public interface IInterceptor
{
Task Invoke(IInvocation invocation, Func next);
}
`invocation` 是方法执行的上下文,`next` 代表后续的逻辑处理,类似于 asp.net core 里的 `next` ,如果不想执行方面的方法不执行 `next` 逻辑即可
### IInterceptorResolver
用来根据当前的执行上下文获取到要执行的拦截器,默认是基于 FluentAPI 的实现,但是如果你特别想用基于 Attribute 的也是可以的,默认提供了一个 `AttributeInterceotorResovler`,你也可以自定义一个适合自己的 `InterceptorResolver`
public interface IInterceptorResolver
{
IReadOnlyList ResolveInterceptors(IInvocation invocation);
}
### IInvocationEnricher
上面 `IInvocation` 的定义中有一个用于扩展的 `Properties`,这个 `enricher` 主要就是基于 `Properties` 来丰富执行上下文信息的,比如说记录 `TraceId` 等请求链路追踪数据,构建方法执行链路等
public interface IEnricher
{
void Enrich(TContext context);
}
public interface IInvocationEnricher : IEnricher
{
}
### AspectDelegate
`AspectDelegate` 是用来将构建要执行的代理方法的方法体的,首先执行注册的 `InvocationEnricher`,丰富上下文信息,然后根据执行上下文获取要执行的拦截器,构建一个执行委托,生成委托使用了之前分享过的 `PipelineBuilder` 构建中间件模式的拦截器,执行拦截器逻辑
// apply enrichers
foreach (var enricher in FluentAspects.AspectOptions.Enrichers)
{
try
{
enricher.Enrich(invocation);
}
catch (Exception ex)
{
InvokeHelper.OnInvokeException?.Invoke(ex);
}
}
// get delegate
var builder = PipelineBuilder.CreateAsync(completeFunc);
foreach (var interceptor in interceptors)
{
builder.Use(interceptor.Invoke);
}
return builder.Build();
更多信息可以参考源码: [https://github.com/WeihanLi/WeihanLi.Common/blob/dev/src/WeihanLi.Common/Aspect/AspectDelegate.cs](https://gitee.com/vip204888/java-p7)
## 使用示例
推荐和依赖注入结合使用,主要分为以微软的注入框架为例,有两种使用方式,一种是手动注册代理服务,一种是自动批量注册代理服务,来看下面的实例就明白了
### 手动注册代理服务
使用方式一,手动注册代理服务:
为了方便使用,提供了一些 `AddProxy` 的扩展方法:
IServiceCollection services = new ServiceCollection();
services.AddFluentAspects(options =>
{
// 注册拦截器配置
options.NoInterceptProperty(f => f.Name);
options.InterceptAll()
.With<LogInterceptor>()
;
options.InterceptMethod<DbContext>(x => x.Name == nameof(DbContext.SaveChanges)
|| x.Name == nameof(DbContext.SaveChangesAsync))
.With<DbContextSaveInterceptor>()
;
options.InterceptMethod<IFly>(f => f.Fly())
.With<LogInterceptor>();
options.InterceptType<IFly>()
.With<LogInterceptor>();
// 注册 InvocationEnricher
options
.WithProperty("TraceId", "121212")
;
});
// 使用 Castle 生成代理
services.AddFluentAspects(options =>
{
// 注册拦截器配置
options.NoInterceptProperty(f => f.Name);
options.InterceptAll()
.With<LogInterceptor>()
;
options.InterceptMethod<DbContext>(x => x.Name == nameof(DbContext.SaveChanges)
|| x.Name == nameof(DbContext.SaveChangesAsync))
.With<DbContextSaveInterceptor>()
;
options.InterceptMethod<IFly>(f => f.Fly())
.With<LogInterceptor>();
options.InterceptType<IFly>()
.With<LogInterceptor>();
// 注册 InvocationEnricher
options
.WithProperty("TraceId", "121212")
;
}, builder => builder.UseCastle());
services.AddTransientProxy<IFly, MonkeyKing>();
services.AddSingletonProxy<IEventBus, EventBus>();
services.AddDbContext(options =>
{
面试资料整理汇总
这些面试题是我朋友进阿里前狂刷七遍以上的面试资料,由于面试文档很多,内容更多,没有办法一一为大家展示出来,所以只好为大家节选出来了一部分供大家参考,需要全部文档的,关注小编后,点击这里即可免费领取。
面试的本质不是考试,而是告诉面试官你会做什么,所以,这些面试资料中提到的技术也是要学会的,不然稍微改动一下你就凉凉了
出来,所以只好为大家节选出来了一部分供大家参考,需要全部文档的,关注小编后,点击这里即可免费领取。
面试的本质不是考试,而是告诉面试官你会做什么,所以,这些面试资料中提到的技术也是要学会的,不然稍微改动一下你就凉凉了
在这里祝大家能够拿到心仪的offer!