using System.Reflection;
using System.Text;
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 Microsoft.Extensions.Options;
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);
}
}