119 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			119 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
using Microsoft.Extensions.Configuration;
 | 
						|
using Microsoft.Extensions.DependencyInjection;
 | 
						|
using System;
 | 
						|
using System.Linq;
 | 
						|
using System.Reflection;
 | 
						|
 | 
						|
namespace FastGithub
 | 
						|
{
 | 
						|
    /// <summary>
 | 
						|
    /// 服务注册扩展
 | 
						|
    /// </summary>
 | 
						|
    public static class ServiceCollectionExtensions
 | 
						|
    {
 | 
						|
        /// <summary>
 | 
						|
        /// 注册程序集下所有服务下选项
 | 
						|
        /// </summary>
 | 
						|
        /// <param name="services"></param>
 | 
						|
        /// <param name="configuration">配置</param>  
 | 
						|
        /// <returns></returns>
 | 
						|
        public static IServiceCollection AddServiceAndOptions(this IServiceCollection services, Assembly assembly, IConfiguration configuration)
 | 
						|
        { 
 | 
						|
            services.AddAttributeServices(assembly);
 | 
						|
            services.AddAttributeOptions(assembly, configuration); 
 | 
						|
 | 
						|
            return services;
 | 
						|
        }
 | 
						|
 | 
						|
        /// <summary>
 | 
						|
        /// 添加程序集下ServiceAttribute标记的服务
 | 
						|
        /// </summary>
 | 
						|
        /// <param name="services"></param>
 | 
						|
        /// <param name="assembly"></param> 
 | 
						|
        /// <returns></returns>
 | 
						|
        private static IServiceCollection AddAttributeServices(this IServiceCollection services, Assembly assembly)
 | 
						|
        {
 | 
						|
            var implTypes = assembly
 | 
						|
                .GetTypes()
 | 
						|
                .Where(item => item.IsClass && item.IsAbstract == false)
 | 
						|
                .ToArray();
 | 
						|
 | 
						|
            foreach (var implType in implTypes)
 | 
						|
            {
 | 
						|
                var attributes = implType.GetCustomAttributes<ServiceAttribute>(false);
 | 
						|
                foreach (var attr in attributes)
 | 
						|
                {
 | 
						|
                    var serviceType = attr.ServiceType ?? implType;
 | 
						|
                    if (services.Any(item => item.ServiceType == serviceType && item.ImplementationType == implType) == false)
 | 
						|
                    {
 | 
						|
                        var descriptor = ServiceDescriptor.Describe(serviceType, implType, attr.Lifetime);
 | 
						|
                        services.Add(descriptor);
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
            return services;
 | 
						|
        }
 | 
						|
 | 
						|
 | 
						|
        /// <summary>
 | 
						|
        /// 添加程序集下OptionsAttribute标记的服务 
 | 
						|
        /// </summary>
 | 
						|
        /// <param name="services"></param>
 | 
						|
        /// <param name="assembly"></param> 
 | 
						|
        /// <param name="configuration"></param>
 | 
						|
        private static IServiceCollection AddAttributeOptions(this IServiceCollection services, Assembly assembly, IConfiguration configuration)
 | 
						|
        {
 | 
						|
            foreach (var optionsType in assembly.GetTypes())
 | 
						|
            {
 | 
						|
                var optionsAttribute = optionsType.GetCustomAttribute<OptionsAttribute>();
 | 
						|
                if (optionsAttribute != null)
 | 
						|
                {
 | 
						|
                    var key = optionsAttribute.SessionKey ?? optionsType.Name;
 | 
						|
                    var section = configuration.GetSection(key);
 | 
						|
                    OptionsBinder.Create(services, optionsType).Bind(section);
 | 
						|
                }
 | 
						|
            }
 | 
						|
            return services;
 | 
						|
        }
 | 
						|
 | 
						|
        /// <summary>
 | 
						|
        /// options绑定器
 | 
						|
        /// </summary>
 | 
						|
        private abstract class OptionsBinder
 | 
						|
        {
 | 
						|
            public abstract void Bind(IConfiguration configuration);
 | 
						|
 | 
						|
            /// <summary>
 | 
						|
            /// 创建OptionsBinder实例
 | 
						|
            /// </summary>
 | 
						|
            /// <param name="services"></param>
 | 
						|
            /// <param name="optionsType"></param>
 | 
						|
            /// <returns></returns>
 | 
						|
            public static OptionsBinder Create(IServiceCollection services, Type optionsType)
 | 
						|
            {
 | 
						|
                var binderType = typeof(OptionsBinderImpl<>).MakeGenericType(optionsType);
 | 
						|
                var binder = Activator.CreateInstance(binderType, new object[] { services });
 | 
						|
 | 
						|
                return binder is OptionsBinder optionsBinder
 | 
						|
                    ? optionsBinder
 | 
						|
                    : throw new TypeInitializationException(binderType.FullName, null);
 | 
						|
            }
 | 
						|
 | 
						|
            private class OptionsBinderImpl<TOptions> : OptionsBinder where TOptions : class
 | 
						|
            {
 | 
						|
                private readonly IServiceCollection services;
 | 
						|
 | 
						|
                public OptionsBinderImpl(IServiceCollection services)
 | 
						|
                {
 | 
						|
                    this.services = services;
 | 
						|
                }
 | 
						|
 | 
						|
                public override void Bind(IConfiguration configuration)
 | 
						|
                {
 | 
						|
                    this.services.AddOptions<TOptions>().Bind(configuration);
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 |