使用 DryIoc 替换 Abp 的 DI 框架 (4)

最开始 Abp 拦截器是在什么时候与具体类型绑定的呢?其实就是在 Castle Windsor 注入组件的时候,各个拦截器注册器都会监听这个组件注入事件。当事件被触发的时候,Abp 各个拦截器注册器都会执行一系列的判断来确保当前类型应该绑定哪一个拦截器。

Abp 自带的拦截器一共有 5 种:工作单元拦截器、参数验证拦截器、授权拦截器、审计日志拦截器、实体历史拦截器。这五种拦截器都是在 AbpBootstrapper 执行创建方法的时候会被调用,调用的时候会监听组件注册事件。

现在的问题是,我们已经没有使用 Castle Windsor 也就没有办法使用 IWindsorContainer 来监听组件注册事件。而 DryIoc 本身也是没有提供这种注入事件的,所以这里我们就只有抽象到 IocManager 类型当中,当 IocManager 的几个注册方法被调用的时候,显式触发一个事件通知这些拦截器注册器对象。

首先我们来到 IIocManager 接口,为其添加一个公开的委托属性,该委托的定义也在下面给出来了。

委托定义:

using System; namespace Abp.Dependency { public delegate void RegisterTypeEventHandler(IIocManager iocManager, Type registerType,Type implementationType); }

IIocManager 接口处新增的属性:

using System; using DryIoc; namespace Abp.Dependency { /// <summary> /// 依赖注入容器管理器, /// 本接口用于执行注入操作 /// </summary> public interface IIocManager : IIocRegistrar, IIocResolver, IDisposable { IContainer IocContainer { get; } new bool IsRegistered(Type type); new bool IsRegistered<T>(); event RegisterTypeEventHandler RegisterTypeEventHandler; } }

之后呢,我们在 IocManager 的 Register() 注册方法内部都显式地触发这个事件。

public void Register(Type type, DependencyLifeStyle lifeStyle = DependencyLifeStyle.Singleton) { IocContainer.Register(type,ApplyLifestyle(lifeStyle), made: Made.Of(FactoryMethod.ConstructorWithResolvableArguments)); RegisterTypeEventHandler?.Invoke(this,type,type); }

就如同这样,实现的效果也是每当有组件注册的时候,都会触发该事件。而各个注册器内部的 Initialize() 方法都传入了一个 IIocManager 对象,所以我们只需要将原有的监听事件改为绑定我们自己定义的事件即可。

下面以工作单元的拦截器注册器为例:

using System.Linq; using System.Reflection; using Abp.Dependency; using Castle.Core; using Castle.MicroKernel; namespace Abp.Domain.Uow { /// <summary> /// This class is used to register interceptor for needed classes for Unit Of Work mechanism. /// </summary> internal static class UnitOfWorkRegistrar { /// <summary> /// Initializes the registerer. /// </summary> /// <param>IOC manager</param> public static void Initialize(IIocManager iocManager) { iocManager.RegisterTypeEventHandler += (manager, type, implementationType) => { var implType = implementationType.GetTypeInfo(); HandleTypesWithUnitOfWorkAttribute(implType,manager); HandleConventionalUnitOfWorkTypes(iocManager, implType); }; } private static void HandleTypesWithUnitOfWorkAttribute(TypeInfo implementationType,IIocManager iocManager) { if (IsUnitOfWorkType(implementationType) || AnyMethodHasUnitOfWork(implementationType)) { // 使用的是上面写的扩展方法 iocManager.IocContainer.Intercept(implementationType,typeof(UnitOfWorkInterceptor)); } } private static void HandleConventionalUnitOfWorkTypes(IIocManager iocManager, TypeInfo implementationType) { if (!iocManager.IsRegistered<IUnitOfWorkDefaultOptions>()) { return; } var uowOptions = iocManager.Resolve<IUnitOfWorkDefaultOptions>(); if (uowOptions.IsConventionalUowClass(implementationType.AsType())) { // 使用的是上面写的扩展方法 iocManager.IocContainer.Intercept(implementationType,typeof(UnitOfWorkInterceptor)); } } private static bool IsUnitOfWorkType(TypeInfo implementationType) { return UnitOfWorkHelper.HasUnitOfWorkAttribute(implementationType); } private static bool AnyMethodHasUnitOfWork(TypeInfo implementationType) { return implementationType .GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) .Any(UnitOfWorkHelper.HasUnitOfWorkAttribute); } } }

按照上面这种步骤,完成剩余拦截器注册器的更改。

4.1.5 收尾工作

如果上述操作都已经完成了的话,那么基本上只剩下 AbpBootstrapper 类型与 AbpKernelModule 几处细小的错误了。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpyypz.html