为了能够通过配置文件(appsettings.json)或通过代码进行背景图片与模板进行配置、可自定义资源类型、自定义验证规则,本节创建一些扩展类,用来实现这些功能。

上一节内容:NET 6 实现滑动验证码(三)、接口


扩展类都放在了Extensions文件夹下

CaptchaBuilderExtensions.cs

CaptchaBuilderExtensions.cs实现了自定义提供验证码背景图片资源或模板资源、自定义实现资源类型、替换默认验证规则、禁用默认凹槽模板

using SlideCaptcha;
using SlideCaptcha.Interface;
using SlideCaptcha.Resources.Provider;
using System.Linq;

namespace Microsoft.Extensions.DependencyInjection
{
    public static class CaptchaBuilderExtensions
    {
        /// <summary>
        /// 自定义提供验证码背景图片资源或模板资源
        /// </summary>
        /// <typeparam name="TProvider">自定义实现</typeparam>
        /// <param name="builder"></param>
        /// <returns></returns>
        public static CaptchaBuilder AddResourceProvider<TProvider>(this CaptchaBuilder builder) where TProvider : class, IResourceProvider
        {
            builder.Services.AddSingleton<IResourceProvider, TProvider>();
            return builder;
        }
        /// <summary>
        /// 自定义实现资源类型
        /// </summary>
        /// <typeparam name="THandler">自定义实现</typeparam>
        /// <param name="builder"></param>
        /// <returns></returns>
        public static CaptchaBuilder AddResourceHandler<THandler>(this CaptchaBuilder builder) where THandler : class, IResourceHandler
        {
            builder.Services.AddSingleton<IResourceHandler, THandler>();
            return builder;
        }
        /// <summary>
        /// 替换默认的验证规则
        /// </summary>
        /// <typeparam name="TValidator">自定义验证规则</typeparam>
        /// <param name="builder"></param>
        /// <returns></returns>
        public static CaptchaBuilder ReplaceValidator<TValidator>(this CaptchaBuilder builder) where TValidator : class, IValidator
        {
            builder.Services.Replace<IValidator, TValidator>();
            return builder;
        }
        /// <summary>
        /// 禁用默认凹槽模板
        /// </summary>
        /// <param name="builder"></param>
        /// <returns></returns>
        public static CaptchaBuilder DisableDefaultTemplates(this CaptchaBuilder builder)
        {
            var serviceDescriptor = builder.Services.FirstOrDefault(e => e.ImplementationType == typeof(EmbeddedResourceProvider));
            if (serviceDescriptor != null)
            {
                builder.Services.Remove(serviceDescriptor);
            }

            return builder;
        }
    }
}

CaptchaServiceCollectionExtensions.cs

CaptchaServiceCollectionExtensions.cs为自动注入必要的接口

using Microsoft.Extensions.Configuration;
using SlideCaptcha;
using SlideCaptcha.Constant;
using SlideCaptcha.Generator;
using SlideCaptcha.Interface;
using SlideCaptcha.Resources;
using SlideCaptcha.Resources.Handler;
using SlideCaptcha.Resources.Provider;
using SlideCaptcha.Storage;
using SlideCaptcha.Validator;
using System;

namespace Microsoft.Extensions.DependencyInjection
{
    public static class CaptchaServiceCollectionExtensions
    {
        /// <summary>
        /// 依赖注入必要的接口。
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        /// <param name="optionsAction"></param>
        /// <returns></returns>
        public static CaptchaBuilder AddSlideCaptcha(this IServiceCollection services, IConfiguration configuration, Action<CaptchaOptions> optionsAction = default)
        {
            services.Configure<CaptchaOptions>(configuration?.GetSection("SlideCaptcha"));
            //对所需验证的参数进行检查,如果参数不合法就抛一个异常出来
            if (optionsAction != null) services.PostConfigure(optionsAction);

            var builder = new CaptchaBuilder(services);
            services.AddSingleton<IResourceProvider, OptionsResourceProvider>();
            services.AddSingleton<IResourceProvider, EmbeddedResourceProvider>();
            services.AddSingleton<IResourceHandlerManager, CachedResourceHandlerManager>();
            services.AddSingleton<IResourceManager, DefaultResourceManager>();
            services.AddSingleton<ISliderCaptchaImageGenerator, SliderCaptchaImageGenerator>();
            services.AddSingleton<IResourceHandler, FileResourceHandler>();
            services.AddSingleton<IResourceHandler, EmbeddedResourceHandler>();
            services.AddScoped<ICaptcha, ImageCaptcha>();
            services.AddScoped<IStorage, DefaultStorage>();
            services.AddScoped<IValidator, SimpleValidator>();
            return builder;
        }
    }
}

ServiceCollectionExtensions.cs

ServiceCollectionExtensions.cs用于实现IServiceCollection的Replace方法

using System;
using System.Collections.Generic;
using System.Linq;


namespace Microsoft.Extensions.DependencyInjection
{
    public static class ServiceCollectionExtensions
    {
        public static IServiceCollection Replace<TService, TImplementation>(this IServiceCollection services)
               where TImplementation : TService
        {
            return services.Replace<TService>(typeof(TImplementation));
        }

        public static IServiceCollection Replace<TService>(this IServiceCollection services, Type implementationType)
        {
            return services.Replace(typeof(TService), implementationType);
        }

        public static IServiceCollection Replace(this IServiceCollection services, Type serviceType, Type implementationType)
        {
            if (services == null)
            {
                throw new ArgumentNullException(nameof(services));
            }

            if (serviceType == null)
            {
                throw new ArgumentNullException(nameof(serviceType));
            }

            if (implementationType == null)
            {
                throw new ArgumentNullException(nameof(implementationType));
            }

            if (!services.TryGetDescriptors(serviceType, out var descriptors))
            {
                throw new ArgumentException($"No services found for {serviceType.FullName}.", nameof(serviceType));
            }

            foreach (var descriptor in descriptors)
            {
                var index = services.IndexOf(descriptor);

                services.Insert(index, descriptor.WithImplementationType(implementationType));

                services.Remove(descriptor);
            }

            return services;
        }

        private static bool TryGetDescriptors(this IServiceCollection services, Type serviceType, out ICollection<ServiceDescriptor> descriptors)
        {
            return (descriptors = services.Where(service => service.ServiceType == serviceType).ToArray()).Any();
        }

        private static ServiceDescriptor WithImplementationType(this ServiceDescriptor descriptor, Type implementationType)
        {
            return new ServiceDescriptor(descriptor.ServiceType, implementationType, descriptor.Lifetime);
        }
    }
}

SlideCaptchaException.cs

SlideCaptchaException.cs 实现自定义异常信息。

using System;

namespace SlideCaptcha.Exceptions
{
    public class SlideCaptchaException : Exception
    {
        public SlideCaptchaException() : base()
        {
        }

        public SlideCaptchaException(string message) : base(message)
        {
        }

        public SlideCaptchaException(string message, Exception innerException) : base(message, innerException)
        {
        }
    }
}

欢迎大家关注我的微信公众号,一起进步,一起成长
.NET 6 实现滑动验证码(四)、扩展类-LMLPHP
12-06 18:24