ABP攔截器

主要介紹ABP框架中攔截器的實現。在AbpBootstrapper中註冊ValidationInterceptorRegistrar驗證攔截器註冊對象,並初始化。app

 /// <summary>
        /// 註冊攔截器
        /// </summary>
        private void AddInterceptorRegistrars()
        {
            ValidationInterceptorRegistrar.Initialize(IocManager);
        }

  ValidationInterceptorRegistrar初始化方法包括篩選合適的攔截條件框架

public static void Initialize(IIocManager iocManager)
        {
            iocManager.IocContainer.Kernel.ComponentRegistered += Kernel_ComponentRegistered;
        }

        private static void Kernel_ComponentRegistered(string key, IHandler handler)
        {
            if (typeof(IApplicationService).GetTypeInfo().IsAssignableFrom(handler.ComponentModel.Implementation))
            {
                handler.ComponentModel.Interceptors.Add(new InterceptorReference(typeof(ValidationInterceptor)));
            }
        }

若是符合條件,則添加ValidationInterceptor攔截器。函數

ValidationInterceptor的實現以下:
/// <summary>
    /// 驗證攔截器
    /// </summary>
    public class ValidationInterceptor : IInterceptor
    {
        private readonly IIocResolver _iocResolver;
        public ValidationInterceptor(IIocResolver iocResolver)
        {
            this._iocResolver = iocResolver;
        }
        public void Intercept(IInvocation invocation)
        {
            using (var validator = _iocResolver.ResolveAsDisposable<MethodInvocationValidator>())
            {
                validator.Object.Initialize(invocation.MethodInvocationTarget, invocation.Arguments);
                validator.Object.Validate();
            }
            invocation.Proceed();
        }
    }

主要經過MethodInvocationValidator中作些操做:this

public class MethodInvocationValidator : ITransientDependency
    {
        #region 聲明實例
        private const int MaxRecursiveParameterValidationDepth = 8;
        protected MethodInfo Method { get; private set; }
        protected object[] ParameterValues { get; private set; }
        protected ParameterInfo[] Parameters { get; private set; }
        protected List<ValidationResult> ValidationErrors { get; }
        private readonly IIocResolver _iocResolver;
        private readonly IValidationConfiguration _configuration;
        #endregion

        #region 構造函數
        public MethodInvocationValidator(IValidationConfiguration configuration, IIocResolver iocResolver)
        {
            _configuration = configuration;
            _iocResolver = iocResolver;
            ValidationErrors = new List<ValidationResult>();
        }
        #endregion
        #region 方法
        /// <summary>
        /// 要驗證的方法
        /// </summary>
        /// <param name="method">方法</param>
        /// <param name="parameterValues">用於調用的參數列表</param>
        public virtual void Initialize(MethodInfo method, object[] parameterValues)
        {
            Method = method;
            ParameterValues = parameterValues;
            Parameters = method.GetParameters();
        }
        public void Validate()
        {
            CheckInitialized();
            if (Parameters.IsNullOrEmpty())
            {
                return;
            }
            if (!Method.IsPublic)
            {
                return;
            }
            if (IsValidationDisabled())
            {
                return;
            }
            if (Parameters.Length != ParameterValues.Length)
            {
                throw new Exception("Method parameter count does not match with argument count!");
            }
            if (ValidationErrors.Any() && HasSingleNullArgument())
            {
                throw new Exception("Method arguments are not valid! See ValidationErrors for details!");
            }
            for (var i = 0; i < Parameters.Length; i++)
            {
                ValidateMethodParameter(Parameters[i], ParameterValues[i]);

            }
        }

        #endregion
        #region 輔助方法
        protected virtual void CheckInitialized()
        {
            if (Method == null)
            {
                throw new Exception("對象未初始化.請先調用初始化方法.");
            }
        }
        protected virtual bool IsValidationDisabled()
        {
            if (Method.IsDefined(typeof(EnableValidationAttribute), true))
            {
                return false;
            }
            return ReflectionHelper.GetSingleAttributeOfMemberOrDeclaringTypeOrDefault<DisableValidationAttribute>(Method) != null;
        }
        protected virtual bool HasSingleNullArgument()
        {
            return Parameters.Length == 1 && ParameterValues[0] == null;
        }
        /// <summary>
        /// 驗證給定值的給定參數。
        /// </summary>
        /// <param name="parameterInfo">要驗證的方法的參數</param>
        /// <param name="parameterValue">要驗證的值</param>
        protected virtual void ValidateMethodParameter(ParameterInfo parameterInfo, object parameterValue)
        {
            if (parameterValue == null)
            {
                if (!parameterInfo.IsOptional &&
                    !parameterInfo.IsOut &&
                    !TypeHelper.IsPrimitiveExtendedIncludingNullable(parameterInfo.ParameterType, includeEnums: true))
                {
                    ValidationErrors.Add(new ValidationResult(parameterInfo.Name + " is null!", new[] { parameterInfo.Name }));
                }

                return;
            }
            ValidateObjectRecursively(parameterValue, 1);
        }

        protected virtual void ValidateObjectRecursively(object validatingObject, int currentDepth)
        {
            if (currentDepth > MaxRecursiveParameterValidationDepth)
            {
                return;
            }
            if (validatingObject == null)
            {
                return;
            }
            SetDataAnnotationAttributeErrors(validatingObject);
            //Validate items of enumerable
            if (validatingObject is IEnumerable && !(validatingObject is IQueryable))
            {
                foreach (var item in (validatingObject as IEnumerable))
                {
                    ValidateObjectRecursively(item, currentDepth + 1);
                }
            }
            if (validatingObject is IEnumerable)
            {
                return;
            }
            var validatingObjectType = validatingObject.GetType();
            //不針對原始對象進行遞歸驗證
            if (TypeHelper.IsPrimitiveExtendedIncludingNullable(validatingObjectType))
            {
                return;
            }
            var properties = TypeDescriptor.GetProperties(validatingObject).Cast<PropertyDescriptor>();
            foreach (var property in properties)
            {
                if (property.Attributes.OfType<DisableValidationAttribute>().Any())
                {
                    continue;
                }

                ValidateObjectRecursively(property.GetValue(validatingObject), currentDepth + 1);
            }
        }
        /// <summary>
        /// 檢查DataAnnotations屬性的全部屬性。
        /// </summary>
        protected virtual void SetDataAnnotationAttributeErrors(object validatingObject)
        {
            var properties = TypeDescriptor.GetProperties(validatingObject).Cast<PropertyDescriptor>();
            foreach (var property in properties)
            {
                var validationAttributes = property.Attributes.OfType<ValidationAttribute>().ToArray();
                if (validationAttributes.IsNullOrEmpty())
                {
                    continue;
                }

                var validationContext = new ValidationContext(validatingObject)
                {
                    DisplayName = property.DisplayName,
                    MemberName = property.Name
                };

                foreach (var attribute in validationAttributes)
                {
                    var result = attribute.GetValidationResult(property.GetValue(validatingObject), validationContext);
                    if (result != null)
                    {
                        ValidationErrors.Add(result);
                    }
                }
            }

            if (validatingObject is IValidatableObject)
            {
                var results = (validatingObject as IValidatableObject).Validate(new ValidationContext(validatingObject));
                ValidationErrors.AddRange(results);
            }
        }
        #endregion
    }

使用攔截器得先註冊,框架中在BasicConventionalRegistrar註冊攔截器spa

public class BasicConventionalRegistrar : IConventionalDependencyRegistrar
    {
        public void RegisterAssembly(IConventionalRegistrationContext context)
        {
            //Windsor Interceptors
            context.IocManager.IocContainer.Register(
              Classes.FromAssembly(context.Assembly)
                  .IncludeNonPublicTypes()
                  .BasedOn<IInterceptor>()
                  .If(type => !type.GetTypeInfo().IsGenericTypeDefinition)
                  .WithService.Self()
                  .LifestyleTransient()
              );
            //註冊攔截器  
            //context.IocManager.IocContainer.Register(
            //    Classes.FromThisAssembly()
            //    .BasedOn<IInterceptor>()
            //    .WithService.Self()
            //    .LifestyleTransient());

            //Transient
            context.IocManager.IocContainer.Register(
                Classes.FromAssembly(context.Assembly)
                    .IncludeNonPublicTypes()
                    .BasedOn<ITransientDependency>()
                    .If(type => !type.GetTypeInfo().IsGenericTypeDefinition)
                    .WithService.Self()
                    .WithService.DefaultInterfaces()
                    .LifestyleTransient()
                );


        }
    }

在各個模塊啓動是調用便可code

相關文章
相關標籤/搜索