今天我们接着之前的系列接着来写另外一种拦截器EntityHistoryInterceptor,这个拦截器到底是做什么的呢?这个从字面上理解是实体历史?这个到底是什么意思?带着这个问题我们来一步步去分析。

  整个拦截器的运行过程和前面几篇是一样的,这里就不再赘述,首先也是在AbpBootstrapper的构造函数中完成初始化过程。

   private void AddInterceptorRegistrars()
{
ValidationInterceptorRegistrar.Initialize(IocManager);
AuditingInterceptorRegistrar.Initialize(IocManager);
EntityHistoryInterceptorRegistrar.Initialize(IocManager);
UnitOfWorkRegistrar.Initialize(IocManager);
AuthorizationInterceptorRegistrar.Initialize(IocManager);
}

  首先我们来从这个Initialize方法来进行说明,然后再来一步步分析。

 internal static class EntityHistoryInterceptorRegistrar
{
public static void Initialize(IIocManager iocManager)
{
iocManager.IocContainer.Kernel.ComponentRegistered += (key, handler) =>
{
if (!iocManager.IsRegistered<IEntityHistoryConfiguration>())
{
return;
} var entityHistoryConfiguration = iocManager.Resolve<IEntityHistoryConfiguration>(); if (ShouldIntercept(entityHistoryConfiguration, handler.ComponentModel.Implementation))
{
handler.ComponentModel.Interceptors.Add(new InterceptorReference(typeof(EntityHistoryInterceptor)));
}
};
} private static bool ShouldIntercept(IEntityHistoryConfiguration entityHistoryConfiguration, Type type)
{
if (type.GetTypeInfo().IsDefined(typeof(UseCaseAttribute), true))
{
return true;
} if (type.GetMethods().Any(m => m.IsDefined(typeof(UseCaseAttribute), true)))
{
return true;
} return false;
}
}

  这个还是和之前一样去订阅IOC容器中的IocContainer.Kernel.ComponentRegistered这个事件,然后在整个ABP框架运行并将每一个接口对应的类型注册到IOC容器的视乎会调用上面订阅的方法。然后在订阅方法中首先判断IOC容器中是否注册过IEntityHistoryConfiguration这个接口,如果没有注册过那么就直接返回了?那么ABP框架到底有没有注册过这个接口呢?

  这个在ABP中的AbpBootstrapper的Initialize方法中就完成了注册,具体的过程就不再描述,重点的是下面这句代码。

 Component.For<IEntityHistoryConfiguration, EntityHistoryConfiguration>().ImplementedBy<EntityHistoryConfiguration>().LifestyleSingleton()

  这个在ABP系统中注册了唯一的一个单例实现EntityHistoryConfiguration这个类,我们来看看这个类的实现。

 internal class EntityHistoryConfiguration : IEntityHistoryConfiguration
{
public bool IsEnabled { get; set; } public bool IsEnabledForAnonymousUsers { get; set; } public IEntityHistorySelectorList Selectors { get; } public List<Type> IgnoredTypes { get; } public EntityHistoryConfiguration()
{
IsEnabled = true;
Selectors = new EntityHistorySelectorList();
IgnoredTypes = new List<Type>()
{
typeof(EntityChangeSet),
typeof(EntityChange),
typeof(EntityPropertyChange)
};
}
}

  我们先不分析这个类到底为了配置些什么,我们接着看EntityHistoryInterceptorRegistrar这个类,在这个类中是否启用拦截,就看当前类型Type中是否定义了自定义属性 UseCaseAttribute,这个属性可以在类上面,也可以定义在类里面的方法中,如果这些类型或者类型里面的方法定义了这个自定义属性,那么就启动后面的拦截过程了,这里面这些类通常是定义在应用层或领域层中的具体和业务相关的类。在判断了这些之后就是添加我们的EntityHistoryInterceptor拦截器了。

  下面我们就来重点分析EntityHistoryInterceptor这个拦截器了。

 internal class EntityHistoryInterceptor : IInterceptor
{
public IEntityChangeSetReasonProvider ReasonProvider { get; set; } public EntityHistoryInterceptor()
{
ReasonProvider = NullEntityChangeSetReasonProvider.Instance;
} public void Intercept(IInvocation invocation)
{
var methodInfo = invocation.MethodInvocationTarget;
var useCaseAttribute = methodInfo.GetCustomAttributes(true).OfType<UseCaseAttribute>().FirstOrDefault()
?? methodInfo.DeclaringType.GetCustomAttributes(true).OfType<UseCaseAttribute>().FirstOrDefault(); if (useCaseAttribute?.Description == null)
{
invocation.Proceed();
return;
} using (ReasonProvider.Use(useCaseAttribute.Description))
{
invocation.Proceed();
}
}
}

  在这个拦截器中,如果一个已拦截的方法在执行前首先会执行Intercept这个方法,在这个方法中我们会往其中的字段Description中添加描述,然后会执行ReasonProvider.Use这个方法,然后将之前的描述Description作为参数进行传递。

ABP中的拦截器之EntityHistoryInterceptor的更多相关文章

  1. ABP中的拦截器之ValidationInterceptor(上)

    从今天这一节起就要深入到ABP中的每一个重要的知识点来一步步进行分析,在进行介绍ABP中的拦截器之前我们先要有个概念,到底什么是拦截器,在介绍这些之前,我们必须要了解AOP编程思想,这个一般翻译是面向 ...

  2. ABP中的拦截器之AuditingInterceptor

    在上面两篇介绍了ABP中的ValidationInterceptor之后,我们今天来看看ABP中定义的另外一种Interceptor即为AuditingInterceptor,顾名思义就是一种审计相关 ...

  3. ABP中的拦截器之ValidationInterceptor(下)

    在上篇我分析了整个ABP中ValitationInterceptor的整个过程,就其中涉及到的Validator过程没有详细的论述,这篇文章就这个过程进行详细的论述,另外任何一个重要的特性如何应用是最 ...

  4. 6. abp中的拦截器

    abp拦截器基本定义 拦截器接口定义: public interface IAbpInterceptor { void Intercept(IAbpMethodInvocation invocatio ...

  5. ABP拦截器之UnitOfWorkRegistrar(一)

    ABP中UnitOfWorkRegistrar拦截器是整个ABP中非常关键的一个部分,这个部分在整个业务系统中也是用的最多的一个部分,这篇文章的主要思路并不是写如何使用ABP中的UnitOfWork, ...

  6. ABP拦截器之AuthorizationInterceptor

    在整体介绍这个部分之前,如果对ABP中的权限控制还没有一个很明确的认知,请先阅读这篇文章,然后在读下面的内容. AuthorizationInterceptor看这个名字我们就知道这个拦截器拦截用户一 ...

  7. ABP拦截器之UnitOfWorkRegistrar(二)

    在上面一篇中我们主要是了解了在ABP系统中是如何使用UnitOfWork以及整个ABP系统中如何执行这些过程的,那么这一篇就让我们来看看UnitOfWorkManager中在执行Begin和Compl ...

  8. ABP源码分析三十五:ABP中动态WebAPI原理解析

    动态WebAPI应该算是ABP中最Magic的功能之一了吧.开发人员无须定义继承自ApiController的类,只须重用Application Service中的类就可以对外提供WebAPI的功能, ...

  9. (实用篇)浅谈PHP拦截器之__set()与__get()的理解与使用方法

    "一般来说,总是把类的属性定义为private,这更符合现实的逻辑. 但是,对属性的读取和赋值操作是非常频繁的,因此在PHP5中,预定义了两个函数"__get()"和&q ...

随机推荐

  1. 23 , CSS 构造列表与导航

    1. 列表图片 2. 背景列表 3. 翻转列表 4. 水平导航 1. 内边距与外边距 Ul { Margin: 0; Padding: 0; } 2. 使用图片作为列表图标 Ul { Margin: ...

  2. mac IDE输入光标变成块状 改为竖线

    mac下安装IDE后,出现“输入光标变成块状”的情况,是因为安装的时候装了ideaVim插件,改为竖线光标的方法:把ideaVim插件去掉

  3. thymeleaf的配置

    1.在springboto项目中使用thymeleaf标签,必须先添加依赖,如下. <dependency> <groupId>org.springframework.boot ...

  4. ListView刷新某一项Item

    ListView现在已经很少被使用,但还是在这里列出来说一下,有时候我们仅仅需要改变listView的某个Item,如果调用adapter的notifyDataSetChanged()方法效率不高,并 ...

  5. Android细笔记--DataStorage

    Shared Preferences 即使应用被杀了,shared preference也还是存在的 Internal Storage 创建于internal的文件只对本应用开放权限,即使手机用户本身 ...

  6. 消息 4900,级别 16,状态 2,第 1 行 对表 'XX.XXX' 执行 ALTER TABLE SWITCH 语句失败。对于已启用更改跟踪的表,不可能切换其分区。请先禁用更改跟踪,再使用 ALTER TABLE SWITCH。

    问题描述: 今天处理切换分区数据的时候出现了这个错误: 消息 4900,级别 16,状态 2,第 1 行 对表 'XX.XXX' 执行 ALTER TABLE SWITCH 语句失败.对于已启用更改跟 ...

  7. LeetCode算法题-Maximum Average Subarray I(Java实现)

    这是悦乐书的第278次更新,第294篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第146题(顺位题号是643).给定由n个整数组成的数组,找到具有最大平均值的长度为k的 ...

  8. Java学习笔记记录(二)

    1.复合语句 if条件语句 使用场景:boolean类型判断.一个范围的判断.几个常量值的判断 有左大括号就没有分号,有分号就没有左大括号. 如下: public class demo1 { stat ...

  9. Dynamics 365 CRM 开发架构简介

    Dynamics 365 CRM提供了多种编程模型,你可以灵活地按需选用最佳模式. 本文是对Dynamics 365 CRM编程模型的综述. 概览 下图表明了Dynamics 365 CRM的主要可编 ...

  10. kernel笔记——块I/O

    Linux下,I/O处理的层次可分为4层: 1. 系统调用层,应用程序使用系统调用指定读写哪个文件,文件偏移是多少  2. 文件系统层,写文件时将用户态中的buffer拷贝到内核态下,并由cache缓 ...