using DS.Module.Core.Exceptions; using DS.Module.Core.Helpers; using DS.Module.Core.Modules; using JetBrains.Annotations; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.FileProviders; using System.Reflection; using System.Text; namespace DS.Module.Core.Extensions; /// /// 服务集合扩展 /// public static class ServiceCollectionExtension { /// /// 得到注入服务 /// /// /// /// public static TType GetService(this IServiceCollection services) { var provider = services.BuildServiceProvider(); return provider.GetService(); } /// /// RegisterAssemblyTypes /// /// services /// assemblies /// services public static IServiceCollection RegisterAssemblyTypes(this IServiceCollection services, params Assembly[] assemblies) => RegisterAssemblyTypes(services, null, ServiceLifetime.Singleton, assemblies); /// /// RegisterAssemblyTypes /// /// services /// service lifetime /// assemblies /// services public static IServiceCollection RegisterAssemblyTypes(this IServiceCollection services, ServiceLifetime serviceLifetime, params Assembly[] assemblies) => RegisterAssemblyTypes(services, null, serviceLifetime, assemblies); /// /// RegisterAssemblyTypes /// /// services /// filter types to register /// assemblies /// services public static IServiceCollection RegisterAssemblyTypes(this IServiceCollection services, Func typesFilter, params Assembly[] assemblies) => RegisterAssemblyTypes(services, typesFilter, ServiceLifetime.Singleton, assemblies); /// /// RegisterAssemblyTypes /// /// services /// filter types to register /// service lifetime /// assemblies /// services public static IServiceCollection RegisterAssemblyTypes(this IServiceCollection services, Func typesFilter, ServiceLifetime serviceLifetime, params Assembly[] assemblies) { if (assemblies == null || assemblies.Length == 0) { assemblies = ReflectHelper.GetAssemblies(); } var types = assemblies .Select(assembly => assembly.GetExportedTypes()) .SelectMany(t => t); if (typesFilter != null) { types = types.Where(typesFilter); } foreach (var type in types) { services.Add(new ServiceDescriptor(type, type, serviceLifetime)); } return services; } /// /// RegisterTypeAsImplementedInterfaces /// /// services /// assemblies /// services public static IServiceCollection RegisterAssemblyTypesAsImplementedInterfaces(this IServiceCollection services, params Assembly[] assemblies) => RegisterAssemblyTypesAsImplementedInterfaces(services, typesFilter: null, ServiceLifetime.Singleton, assemblies); /// /// RegisterTypeAsImplementedInterfaces /// /// services /// service lifetime /// assemblies /// services public static IServiceCollection RegisterAssemblyTypesAsImplementedInterfaces(this IServiceCollection services, ServiceLifetime serviceLifetime, params Assembly[] assemblies) => RegisterAssemblyTypesAsImplementedInterfaces(services, typesFilter: null, serviceLifetime, assemblies); /// /// RegisterTypeAsImplementedInterfaces, singleton by default /// /// services /// filter types to register /// assemblies /// services public static IServiceCollection RegisterAssemblyTypesAsImplementedInterfaces(this IServiceCollection services, Func typesFilter, params Assembly[] assemblies) => RegisterAssemblyTypesAsImplementedInterfaces(services, typesFilter: typesFilter, ServiceLifetime.Singleton, assemblies); /// /// RegisterTypeAsImplementedInterfaces /// /// services /// filter types to register /// service lifetime /// assemblies /// services public static IServiceCollection RegisterAssemblyTypesAsImplementedInterfaces(this IServiceCollection services, Func typesFilter, ServiceLifetime serviceLifetime, params Assembly[] assemblies) { if (assemblies == null || assemblies.Length == 0) { assemblies = ReflectHelper.GetAssemblies(); } var types = assemblies .Select(assembly => assembly.GetExportedTypes()) .SelectMany(t => t); if (typesFilter != null) { types = types.Where(typesFilter); } foreach (var type in types) { foreach (var implementedInterface in type.GetImplementedInterfaces()) { services.Add(new ServiceDescriptor(implementedInterface, type, serviceLifetime)); } } return services; } /// /// RegisterTypeAsImplementedInterfaces /// /// services /// type /// service lifetime /// services public static IServiceCollection RegisterTypeAsImplementedInterfaces(this IServiceCollection services, Type type, ServiceLifetime serviceLifetime = ServiceLifetime.Singleton) { if (type != null) { foreach (var interfaceType in type.GetImplementedInterfaces()) { services.Add(new ServiceDescriptor(interfaceType, type, serviceLifetime)); } } return services; } /// /// 得到注入服务 /// /// /// /// public static TType GetBuildService(this IServiceCollection services) { var provider = services.BuildServiceProvider(); return provider.GetService(); } /// /// 得到或添加Singleton服务 /// /// /// /// /// public static TServiceType GetOrAddSingletonService(this IServiceCollection services) where TServiceType : class where TImplementation : class, TServiceType { var type = services.GetSingletonInstanceOrNull(); if (type is null) { var provider = services.BuildServiceProvider(); var serviceType = (TServiceType)provider.GetInstance(new ServiceDescriptor(typeof(TServiceType), typeof(TImplementation), ServiceLifetime.Singleton)); return serviceType; } return type; } /// /// 得到或添加Singleton服务 /// /// public static TServiceType GetOrAddSingletonService(this IServiceCollection services, Func factory) where TServiceType : class { var servciceType = services.GetSingletonInstanceOrNull(); if (servciceType is null) { servciceType = factory(); services.AddSingleton(servciceType); } return servciceType; } public static IConfiguration GetConfiguration(this IServiceCollection services) { return services.GetBuildService(); } /// /// 获取单例注册服务对象 /// public static T GetSingletonInstanceOrNull(this IServiceCollection services) { ServiceDescriptor descriptor = services.FirstOrDefault(d => d.ServiceType == typeof(T) && d.Lifetime == ServiceLifetime.Singleton); if (descriptor?.ImplementationInstance != null) { return (T)descriptor.ImplementationInstance; } if (descriptor?.ImplementationFactory != null) { return (T)descriptor.ImplementationFactory.Invoke(null); } return default; } // /// // /// 得到操作设置 // /// // /// // /// // public static AppOptionSettings GetAppSettings(this IServiceCollection services) // { // services.NotNull(nameof(services)); // return services.GetBuildService>()?.Value; // } public static T GetSingletonInstance(this IServiceCollection services) { var service = services.GetSingletonInstanceOrNull(); if (service == null) { throw new InvalidOperationException("找不到singleton服务: " + typeof(T).AssemblyQualifiedName); } return service; } #region New Module public static ObjectAccessor TryAddObjectAccessor(this IServiceCollection services) { if (services.Any(s => s.ServiceType == typeof(ObjectAccessor))) { return services.GetSingletonInstance>(); } return services.AddObjectAccessor(); } public static ObjectAccessor AddObjectAccessor(this IServiceCollection services) { return services.AddObjectAccessor(new ObjectAccessor()); } public static ObjectAccessor AddObjectAccessor(this IServiceCollection services, T obj) { return services.AddObjectAccessor(new ObjectAccessor(obj)); } public static ObjectAccessor AddObjectAccessor(this IServiceCollection services, ObjectAccessor accessor) { if (services.Any(s => s.ServiceType == typeof(ObjectAccessor))) { throw new Exception("在类型“{typeof(T).AssemblyQualifiedName)}”之前注册了对象: "); } //Add to the beginning for fast retrieve services.Insert(0, ServiceDescriptor.Singleton(typeof(ObjectAccessor), accessor)); services.Insert(0, ServiceDescriptor.Singleton(typeof(IObjectAccessor), accessor)); return accessor; } public static T GetObjectOrNull(this IServiceCollection services) where T : class { return services.GetSingletonInstanceOrNull>()?.Value; } public static T GetObject(this IServiceCollection services) where T : class { return services.GetObjectOrNull() ?? throw new Exception($"找不到的对象 {typeof(T).AssemblyQualifiedName} 服务。请确保您以前使用过AddObjectAccessor!"); } public static IServiceProvider BuildServiceProviderFromFactory([NotNull] this IServiceCollection services) { foreach (var service in services) { var factoryInterface = service.ImplementationInstance?.GetType() .GetTypeInfo() .GetInterfaces() .FirstOrDefault(i => i.GetTypeInfo().IsGenericType && i.GetGenericTypeDefinition() == typeof(IServiceProviderFactory<>)); if (factoryInterface == null) { continue; } var containerBuilderType = factoryInterface.GenericTypeArguments[0]; return (IServiceProvider)typeof(Extensions) .GetTypeInfo() .GetMethods() .Single(m => m.Name == nameof(BuildServiceProviderFromFactory) && m.IsGenericMethod) .MakeGenericMethod(containerBuilderType) .Invoke(null, new object[] { services, null }); } return services.BuildServiceProvider(); } #endregion New Module /// /// 得到文件容器 /// /// 服务接口 /// 文件名+后缀名 /// 文件不存提示信息 /// 返回文件中的文件 public static string GetFileText(this IServiceCollection services, string fileName, string fileNotExistsMsg) { fileName.NotNullOrEmpty(nameof(fileName)); var fileProvider = services.GetSingletonInstanceOrNull(); if (fileProvider == null) { throw new DSAppException("IFileProvider接口不存在"); } var fileInfo = fileProvider.GetFileInfo(fileName); if (!fileInfo.Exists) { if (!fileNotExistsMsg.IsNullOrEmpty()) { throw new DSAppException(fileNotExistsMsg); } } var text = ReadAllText(fileInfo); if (text.IsNullOrEmpty()) { throw new DSAppException("文件内容不存在"); } return text; } /// /// 根据配置得到文件内容 /// /// 服务接口 /// 分区键 /// 文件不存提示信息 /// 返回文件中的文件 public static string GetFileByConfiguration(this IServiceCollection services, string sectionKey, string fileNotExistsMsg) { sectionKey.NotNullOrEmpty(nameof(sectionKey)); var configuration = services.GetService(); var value = configuration?.GetSection(sectionKey)?.Value; return services.GetFileText(value, fileNotExistsMsg); } /// /// 读取全部文本 /// /// 文件信息接口 /// private static string ReadAllText(IFileInfo fileInfo) { byte[] buffer; using var stream = fileInfo.CreateReadStream(); buffer = new byte[stream.Length]; stream.Read(buffer, 0, buffer.Length); return Encoding.Default.GetString(buffer).Trim(); } /// /// 添加文件提供器 /// /// /// public static IServiceCollection AddFileProvider(this IServiceCollection services) { var basePath = Microsoft.DotNet.PlatformAbstractions.ApplicationEnvironment.ApplicationBasePath; //获取项目路径 return services.AddSingleton(new PhysicalFileProvider(basePath)); } /// /// 获取指定key的值,如没有则设置并获取默认值 /// /// key的类型 /// value的类型 /// 字典 /// key /// 默认值委托 /// public static TValue GetOrAdd(this IDictionary dict, TKey key, Func func) { if (dict.TryGetValue(key, out var obj)) { return obj; } return dict[key] = func(key); } }