mirror of
				https://gitee.com/ThingsGateway/ThingsGateway.git
				synced 2025-11-04 01:23:58 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			307 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			307 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
// ------------------------------------------------------------------------
 | 
						||
// 版权信息
 | 
						||
// 版权归百小僧及百签科技(广东)有限公司所有。
 | 
						||
// 所有权利保留。
 | 
						||
// 官方网站:https://baiqian.com
 | 
						||
//
 | 
						||
// 许可证信息
 | 
						||
// 项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。
 | 
						||
// 许可证的完整文本可以在源代码树根目录中的 LICENSE-APACHE 和 LICENSE-MIT 文件中找到。
 | 
						||
// ------------------------------------------------------------------------
 | 
						||
 | 
						||
using Microsoft.Extensions.Hosting;
 | 
						||
 | 
						||
using System.Reflection;
 | 
						||
using System.Text;
 | 
						||
 | 
						||
using ThingsGateway;
 | 
						||
using ThingsGateway.NewLife.Caching;
 | 
						||
using ThingsGateway.NewLife.Redis.Extensions;
 | 
						||
using ThingsGateway.UnifyResult;
 | 
						||
 | 
						||
namespace Microsoft.Extensions.DependencyInjection;
 | 
						||
 | 
						||
/// <summary>
 | 
						||
/// 应用服务集合拓展类(由框架内部调用)
 | 
						||
/// </summary>
 | 
						||
[SuppressSniffer]
 | 
						||
public static class AppServiceCollectionExtensions
 | 
						||
{
 | 
						||
    /// <summary>
 | 
						||
    /// Mvc 注入基础配置(带Swagger)
 | 
						||
    /// </summary>
 | 
						||
    /// <param name="mvcBuilder">Mvc构建器</param>
 | 
						||
    /// <param name="configure"></param>
 | 
						||
    /// <returns>IMvcBuilder</returns>
 | 
						||
    public static IMvcBuilder AddInject(this IMvcBuilder mvcBuilder, Action<AddInjectOptions> configure = null)
 | 
						||
    {
 | 
						||
        mvcBuilder.Services.AddInject(configure);
 | 
						||
 | 
						||
        return mvcBuilder;
 | 
						||
    }
 | 
						||
 | 
						||
    /// <summary>
 | 
						||
    /// 服务注入基础配置(带Swagger)
 | 
						||
    /// </summary>
 | 
						||
    /// <param name="services">服务集合</param>
 | 
						||
    /// <param name="configure"></param>
 | 
						||
    /// <returns>IMvcBuilder</returns>
 | 
						||
    public static IServiceCollection AddInject(this IServiceCollection services, Action<AddInjectOptions> configure = null)
 | 
						||
    {
 | 
						||
        // 载入服务配置选项
 | 
						||
        var configureOptions = new AddInjectOptions();
 | 
						||
        configure?.Invoke(configureOptions);
 | 
						||
 | 
						||
        services.AddSpecificationDocuments(AddInjectOptions.SwaggerGenConfigure)
 | 
						||
                .AddDynamicApiControllers()
 | 
						||
                .AddDataValidation(AddInjectOptions.DataValidationConfigure)
 | 
						||
                .AddFriendlyException(AddInjectOptions.FriendlyExceptionConfigure);
 | 
						||
 | 
						||
        return services;
 | 
						||
    }
 | 
						||
 | 
						||
    /// <summary>
 | 
						||
    /// MiniAPI 服务注入基础配置(带Swagger)
 | 
						||
    /// </summary>
 | 
						||
    /// <param name="services">服务集合</param>
 | 
						||
    /// <param name="configure"></param>
 | 
						||
    /// <returns>IMvcBuilder</returns>
 | 
						||
    /// <remarks>https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/minimal-apis?view=aspnetcore-6.0</remarks>
 | 
						||
    public static IServiceCollection AddInjectMini(this IServiceCollection services, Action<AddInjectOptions> configure = null)
 | 
						||
    {
 | 
						||
        // 载入服务配置选项
 | 
						||
        var configureOptions = new AddInjectOptions();
 | 
						||
        configure?.Invoke(configureOptions);
 | 
						||
 | 
						||
        services.AddSpecificationDocuments(AddInjectOptions.SwaggerGenConfigure)
 | 
						||
                .AddDataValidation(AddInjectOptions.DataValidationConfigure)
 | 
						||
                .AddFriendlyException(AddInjectOptions.FriendlyExceptionConfigure);
 | 
						||
 | 
						||
        return services;
 | 
						||
    }
 | 
						||
 | 
						||
    /// <summary>
 | 
						||
    /// Mvc 注入基础配置
 | 
						||
    /// </summary>
 | 
						||
    /// <param name="mvcBuilder">Mvc构建器</param>
 | 
						||
    /// <param name="configure"></param>
 | 
						||
    /// <returns>IMvcBuilder</returns>
 | 
						||
    public static IMvcBuilder AddInjectBase(this IMvcBuilder mvcBuilder, Action<AddInjectOptions> configure = null)
 | 
						||
    {
 | 
						||
        mvcBuilder.Services.AddInjectBase(configure);
 | 
						||
 | 
						||
        return mvcBuilder;
 | 
						||
    }
 | 
						||
 | 
						||
    /// <summary>
 | 
						||
    /// Mvc 注入基础配置
 | 
						||
    /// </summary>
 | 
						||
    /// <param name="services">服务集合</param>
 | 
						||
    /// <param name="configure"></param>
 | 
						||
    /// <returns>IMvcBuilder</returns>
 | 
						||
    public static IServiceCollection AddInjectBase(this IServiceCollection services, Action<AddInjectOptions> configure = null)
 | 
						||
    {
 | 
						||
        // 载入服务配置选项
 | 
						||
        var configureOptions = new AddInjectOptions();
 | 
						||
        configure?.Invoke(configureOptions);
 | 
						||
 | 
						||
        services.AddDataValidation(AddInjectOptions.DataValidationConfigure)
 | 
						||
                .AddFriendlyException(AddInjectOptions.FriendlyExceptionConfigure);
 | 
						||
 | 
						||
        return services;
 | 
						||
    }
 | 
						||
 | 
						||
    /// <summary>
 | 
						||
    /// Mvc 注入基础配置和规范化结果
 | 
						||
    /// </summary>
 | 
						||
    /// <param name="mvcBuilder"></param>
 | 
						||
    /// <param name="configure"></param>
 | 
						||
    /// <returns></returns>
 | 
						||
    public static IMvcBuilder AddInjectWithUnifyResult(this IMvcBuilder mvcBuilder, Action<AddInjectOptions> configure = null)
 | 
						||
    {
 | 
						||
        mvcBuilder.Services.AddInjectWithUnifyResult(configure);
 | 
						||
 | 
						||
        return mvcBuilder;
 | 
						||
    }
 | 
						||
 | 
						||
    /// <summary>
 | 
						||
    /// 注入基础配置和规范化结果
 | 
						||
    /// </summary>
 | 
						||
    /// <param name="services"></param>
 | 
						||
    /// <param name="configure"></param>
 | 
						||
    /// <returns></returns>
 | 
						||
    public static IServiceCollection AddInjectWithUnifyResult(this IServiceCollection services, Action<AddInjectOptions> configure = null)
 | 
						||
    {
 | 
						||
        services.AddInject(configure)
 | 
						||
                .AddUnifyResult();
 | 
						||
 | 
						||
        return services;
 | 
						||
    }
 | 
						||
 | 
						||
    /// <summary>
 | 
						||
    /// Mvc 注入基础配置和规范化结果
 | 
						||
    /// </summary>
 | 
						||
    /// <typeparam name="TUnifyResultProvider"></typeparam>
 | 
						||
    /// <param name="mvcBuilder"></param>
 | 
						||
    /// <param name="configure"></param>
 | 
						||
    /// <returns></returns>
 | 
						||
    public static IMvcBuilder AddInjectWithUnifyResult<TUnifyResultProvider>(this IMvcBuilder mvcBuilder, Action<AddInjectOptions> configure = null)
 | 
						||
        where TUnifyResultProvider : class, IUnifyResultProvider
 | 
						||
    {
 | 
						||
        mvcBuilder.Services.AddInjectWithUnifyResult<TUnifyResultProvider>(configure);
 | 
						||
 | 
						||
        return mvcBuilder;
 | 
						||
    }
 | 
						||
 | 
						||
    /// <summary>
 | 
						||
    /// Mvc 注入基础配置和规范化结果
 | 
						||
    /// </summary>
 | 
						||
    /// <typeparam name="TUnifyResultProvider"></typeparam>
 | 
						||
    /// <param name="configure"></param>
 | 
						||
    /// <param name="services"></param>
 | 
						||
    /// <returns></returns>
 | 
						||
    public static IServiceCollection AddInjectWithUnifyResult<TUnifyResultProvider>(this IServiceCollection services, Action<AddInjectOptions> configure = null)
 | 
						||
        where TUnifyResultProvider : class, IUnifyResultProvider
 | 
						||
    {
 | 
						||
        services.AddInject(configure)
 | 
						||
                .AddUnifyResult<TUnifyResultProvider>();
 | 
						||
 | 
						||
        return services;
 | 
						||
    }
 | 
						||
 | 
						||
    /// <summary>
 | 
						||
    /// 自动添加主机服务
 | 
						||
    /// </summary>
 | 
						||
    /// <param name="services"></param>
 | 
						||
    /// <returns></returns>
 | 
						||
    public static IServiceCollection AddAppHostedService(this IServiceCollection services)
 | 
						||
    {
 | 
						||
        // 获取所有 BackgroundService 类型,排除泛型主机
 | 
						||
        var backgroundServiceTypes = App.EffectiveTypes.Where(u => !u.IsAbstract && !u.IsInterface && !u.IsGenericType
 | 
						||
                    && typeof(IHostedService).IsAssignableFrom(u) && u.Name != "GenericWebHostService"
 | 
						||
                    && !services.Any(c => c.ServiceType == typeof(IHostedService) && c.ImplementationType != u));
 | 
						||
 | 
						||
        var addHostServiceMethod = typeof(ServiceCollectionHostedServiceExtensions).GetMethods(BindingFlags.Static | BindingFlags.Public)
 | 
						||
                            .Where(u => u.Name.Equals("AddHostedService") && u.IsGenericMethod && u.GetParameters().Length == 1)
 | 
						||
                            .FirstOrDefault();
 | 
						||
 | 
						||
        foreach (var type in backgroundServiceTypes)
 | 
						||
        {
 | 
						||
            addHostServiceMethod.MakeGenericMethod(type).Invoke(null, new object[] { services });
 | 
						||
        }
 | 
						||
 | 
						||
        return services;
 | 
						||
    }
 | 
						||
 | 
						||
    /// <summary>
 | 
						||
    /// 添加应用配置
 | 
						||
    /// </summary>
 | 
						||
    /// <param name="services">服务集合</param>
 | 
						||
    /// <param name="configure">服务配置</param>
 | 
						||
    /// <returns>服务集合</returns>
 | 
						||
    internal static IServiceCollection AddApp(this IServiceCollection services, Action<IServiceCollection> configure = null)
 | 
						||
    {
 | 
						||
        // 注册全局配置选项
 | 
						||
        services.AddConfigurableOptions<AppSettingsOptions>();
 | 
						||
        services.AddConfigurableOptions<CacheOptions>();
 | 
						||
 | 
						||
        // 注册内存和分布式内存
 | 
						||
        services.AddMemoryCache();
 | 
						||
        services.AddDistributedMemoryCache();
 | 
						||
 | 
						||
        var cacheOptions = App.GetConfig<CacheOptions>("Cache", true);
 | 
						||
        // 缓存
 | 
						||
        if (cacheOptions.CacheType == CacheType.Memory)
 | 
						||
        {
 | 
						||
            services.AddSingleton<ICache>(a =>
 | 
						||
            {
 | 
						||
                Cache.Default = new MemoryCache()
 | 
						||
                {
 | 
						||
                    Capacity = cacheOptions.MemoryCacheOptions.Capacity,
 | 
						||
                    Expire = cacheOptions.MemoryCacheOptions.Expire,
 | 
						||
                    Period = cacheOptions.MemoryCacheOptions.Period
 | 
						||
                };
 | 
						||
                return Cache.Default;
 | 
						||
            }
 | 
						||
        );
 | 
						||
 | 
						||
        }
 | 
						||
        else if (cacheOptions.CacheType == CacheType.Redis)
 | 
						||
        {
 | 
						||
            services.AddDistributedRedisCache(options =>
 | 
						||
            {
 | 
						||
                options.Db = cacheOptions.RedisCacheOptions.Db;
 | 
						||
                options.Configuration = cacheOptions.RedisCacheOptions.Configuration;
 | 
						||
                options.UserName = cacheOptions.RedisCacheOptions.UserName;
 | 
						||
                options.Password = cacheOptions.RedisCacheOptions.Password;
 | 
						||
                options.Server = cacheOptions.RedisCacheOptions.Server;
 | 
						||
                options.Timeout = cacheOptions.RedisCacheOptions.Timeout;
 | 
						||
                options.Prefix = cacheOptions.RedisCacheOptions.Prefix;
 | 
						||
                options.InstanceName = cacheOptions.RedisCacheOptions.InstanceName;
 | 
						||
                options.Expire = cacheOptions.RedisCacheOptions.Expire;
 | 
						||
            });
 | 
						||
        }
 | 
						||
 | 
						||
        // 注册全局依赖注入
 | 
						||
        services.AddDependencyInjection();
 | 
						||
 | 
						||
        // 注册全局 Startup 扫描
 | 
						||
        services.AddStartups();
 | 
						||
 | 
						||
        // 添加对象映射
 | 
						||
        //services.AddObjectMapper();
 | 
						||
 | 
						||
        // 默认内置 GBK,Windows-1252, Shift-JIS, GB2312 编码支持
 | 
						||
        Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
 | 
						||
 | 
						||
        // 自定义服务
 | 
						||
        configure?.Invoke(services);
 | 
						||
 | 
						||
        return services;
 | 
						||
    }
 | 
						||
 | 
						||
    /// <summary>
 | 
						||
    /// 添加 Startup 自动扫描
 | 
						||
    /// </summary>
 | 
						||
    /// <param name="services">服务集合</param>
 | 
						||
    /// <returns>服务集合</returns>
 | 
						||
    internal static IServiceCollection AddStartups(this IServiceCollection services)
 | 
						||
    {
 | 
						||
        // 扫描所有继承 AppStartup 的类
 | 
						||
        var startups = App.EffectiveTypes
 | 
						||
            .Where(u => typeof(AppStartup).IsAssignableFrom(u) && u.IsClass && !u.IsAbstract && !u.IsGenericType)
 | 
						||
            .OrderByDescending(u => GetStartupOrder(u));
 | 
						||
 | 
						||
        // 注册自定义 startup
 | 
						||
        foreach (var type in startups)
 | 
						||
        {
 | 
						||
            var startup = Activator.CreateInstance(type) as AppStartup;
 | 
						||
            App.AppStartups.Add(startup);
 | 
						||
 | 
						||
            // 获取所有符合依赖注入格式的方法,如返回值void,且第一个参数是 IServiceCollection 类型
 | 
						||
            var serviceMethods = type.GetMethods(BindingFlags.Public | BindingFlags.Instance)
 | 
						||
                .Where(u => u.ReturnType == typeof(void)
 | 
						||
                    && u.GetParameters().Length > 0
 | 
						||
                    && u.GetParameters().First().ParameterType == typeof(IServiceCollection));
 | 
						||
 | 
						||
 | 
						||
            // 自动安装属性调用
 | 
						||
            foreach (var method in serviceMethods)
 | 
						||
            {
 | 
						||
                method.Invoke(startup, new[] { services });
 | 
						||
            }
 | 
						||
        }
 | 
						||
 | 
						||
        return services;
 | 
						||
    }
 | 
						||
 | 
						||
    /// <summary>
 | 
						||
    /// 获取 Startup 排序
 | 
						||
    /// </summary>
 | 
						||
    /// <param name="type">排序类型</param>
 | 
						||
    /// <returns>int</returns>
 | 
						||
    private static int GetStartupOrder(Type type)
 | 
						||
    {
 | 
						||
        return !type.IsDefined(typeof(AppStartupAttribute), true) ? 0 : type.GetCustomAttribute<AppStartupAttribute>(true).Order;
 | 
						||
    }
 | 
						||
} |