非依赖注入管道中获取所有服务

1.导入包

<PackageReference Include="Serilog.AspNetCore" Version="8.0.0" />
<PackageReference Include="Serilog.Sinks.Async" Version="1.5.0" />

2.配置RuntimeExtension类

public static class RuntimeExtension
{
    /// <summary>
    /// 获取项目程序集,排除所有的系统程序集(Microsoft.***、System.***等)、Nuget下载包
    /// </summary>
    /// <returns></returns>
    public static IList<Assembly> GetAllAssemblies()
    {
        var list = new List<Assembly>();
        var deps = DependencyContext.Default;
        //只加载项目中的程序集
        var libs = deps.CompileLibraries.Where(lib => !lib.Serviceable && lib.Type == "project"); //排除所有的系统程序集、Nuget下载包
        foreach (var lib in libs)
        {
            try
            {
                var assembly = AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(lib.Name));
                list.Add(assembly);
            }
            catch (Exception e)
            {
                Log.Debug(e, "GetAllAssemblies Exception:{ex}", e.Message);
            }
        }

        return list;
    }

    public static Assembly GetAssembly(string assemblyName)
    {
        return GetAllAssemblies().FirstOrDefault(assembly => assembly.FullName.Contains(assemblyName));
    }

    public static IList<Type> GetAllTypes()
    {
        var list = new List<Type>();
        foreach (var assembly in GetAllAssemblies())
        {
            var typeInfos = assembly.DefinedTypes;
            foreach (var typeInfo in typeInfos)
            {
                list.Add(typeInfo.AsType());
            }
        }

        return list;
    }

    public static IList<Type> GetTypesByAssembly(string assemblyName)
    {
        var list = new List<Type>();
        var assembly = AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(assemblyName));
        var typeInfos = assembly.DefinedTypes;
        foreach (var typeInfo in typeInfos)
        {
            list.Add(typeInfo.AsType());
        }

        return list;
    }

    public static Type GetImplementType(string typeName, Type baseInterfaceType)
    {
        return GetAllTypes().FirstOrDefault(t =>
        {
            if (t.Name == typeName &&
                t.GetTypeInfo().GetInterfaces().Any(b => b.Name == baseInterfaceType.Name))
            {
                var typeInfo = t.GetTypeInfo();
                return typeInfo.IsClass && !typeInfo.IsAbstract && !typeInfo.IsGenericType;
            }

            return false;
        });
    }
}

3.配置InternalApp类

/// <summary>
/// 内部只用于初始化使用
/// </summary>
public static class InternalApp
{
    internal static IServiceCollection InternalServices;

    /// <summary>
    /// 根服务
    /// </summary>
    internal static IServiceProvider RootServices;

    /// <summary>
    /// 获取web主机环境
    /// </summary>
    internal static IWebHostEnvironment WebHostEnvironment;

    /// <summary>
    /// 获取泛型主机环境
    /// </summary>
    internal static IHostEnvironment HostEnvironment;

    /// <summary>
    /// 配置对象
    /// </summary>
    internal static IConfiguration Configuration;


    public static void ConfigureApplication(this WebApplicationBuilder wab)
    {
        WebHostEnvironment = wab.Environment;
        HostEnvironment = wab.Environment;
        InternalServices = wab.Services;
    }

    public static void ConfigureApplication(this IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public static void ConfigureApplication(this IHost app)
    {
        RootServices = app.Services;
    }
}

4.配置IUser接口

 public interface IUser
 {
     string Name { get; }
     long ID { get; }
     long TenantId { get; }
     bool IsAuthenticated();
     IEnumerable<Claim> GetClaimsIdentity();
     List<string> GetClaimValueByType(string ClaimType);

     string GetToken();
     List<string> GetUserInfoFromToken(string ClaimType);
 }

5.配置APP类

public class App
{
    static App()
    {
        EffectiveTypes = Assemblies.SelectMany(GetTypes);
    }

    private static bool _isRun;

    /// <summary>是否正在运行</summary>
    public static bool IsBuild { get; set; }

    public static bool IsRun
    {
        get => _isRun;
        set => _isRun = IsBuild = value;
    }

    /// <summary>应用有效程序集</summary>
    public static readonly IEnumerable<Assembly> Assemblies = RuntimeExtension.GetAllAssemblies();

    /// <summary>有效程序集类型</summary>
    public static readonly IEnumerable<Type> EffectiveTypes;

    /// <summary>优先使用App.GetService()手动获取服务</summary>
    public static IServiceProvider RootServices => IsRun || IsBuild ? InternalApp.RootServices : null;

    /// <summary>获取Web主机环境,如,是否是开发环境,生产环境等</summary>
    public static IWebHostEnvironment WebHostEnvironment => InternalApp.WebHostEnvironment;

    /// <summary>获取泛型主机环境,如,是否是开发环境,生产环境等</summary>
    public static IHostEnvironment HostEnvironment => InternalApp.HostEnvironment;

    /// <summary>全局配置选项</summary>
    public static IConfiguration Configuration => InternalApp.Configuration;

    /// <summary>
    /// 获取请求上下文
    /// </summary>
    public static HttpContext HttpContext => RootServices?.GetService<IHttpContextAccessor>()?.HttpContext;

    public static IUser User => GetService<IUser>();

    #region Service

    /// <summary>解析服务提供器</summary>
    /// <param name="serviceType"></param>
    /// <param name="mustBuild"></param>
    /// <param name="throwException"></param>
    /// <returns></returns>
    public static IServiceProvider GetServiceProvider(Type serviceType, bool mustBuild = false, bool throwException = true)
    {
        if (HostEnvironment == null || RootServices != null &&
            InternalApp.InternalServices
                .Where(u =>
                    u.ServiceType ==
                    (serviceType.IsGenericType ? serviceType.GetGenericTypeDefinition() : serviceType))
                .Any(u => u.Lifetime == ServiceLifetime.Singleton))
            return RootServices;

        //获取请求生存周期的服务
        if (HttpContext?.RequestServices != null)
            return HttpContext.RequestServices;

        if (RootServices != null)
        {
            IServiceScope scope = RootServices.CreateScope();
            return scope.ServiceProvider;
        }

        if (mustBuild)
        {
            if (throwException)
            {
                throw new ApplicationException("当前不可用,必须要等到 WebApplication Build后");
            }

            return default;
        }

        ServiceProvider serviceProvider = InternalApp.InternalServices.BuildServiceProvider();
        return serviceProvider;
    }

    public static TService GetService<TService>(bool mustBuild = true) where TService : class =>
        GetService(typeof(TService), null, mustBuild) as TService;

    /// <summary>获取请求生存周期的服务</summary>
    /// <typeparam name="TService"></typeparam>
    /// <param name="serviceProvider"></param>
    /// <param name="mustBuild"></param>
    /// <returns></returns>
    public static TService GetService<TService>(IServiceProvider serviceProvider, bool mustBuild = true)
        where TService : class => (serviceProvider ?? GetServiceProvider(typeof(TService), mustBuild, false))?.GetService<TService>();

    /// <summary>获取请求生存周期的服务</summary>
    /// <param name="type"></param>
    /// <param name="serviceProvider"></param>
    /// <param name="mustBuild"></param>
    /// <returns></returns>
    public static object GetService(Type type, IServiceProvider serviceProvider = null, bool mustBuild = true) =>
        (serviceProvider ?? GetServiceProvider(type, mustBuild, false))?.GetService(type);

    #endregion

    #region private

    /// <summary>加载程序集中的所有类型</summary>
    /// <param name="ass"></param>
    /// <returns></returns>
    private static IEnumerable<Type> GetTypes(Assembly ass)
    {
        Type[] source = Array.Empty<Type>();
        try
        {
            source = ass.GetTypes();
        }
        catch
        {
            Console.WriteLine($@"Error load `{ass.FullName}` assembly.");
        }

        return source.Where(u => u.IsPublic);
    }

    #endregion

    #region Options

    /// <summary>获取配置</summary>
    /// <typeparam name="TOptions">强类型选项类</typeparam>
    /// <returns>TOptions</returns>
    public static TOptions GetConfig<TOptions>()
        where TOptions : class, IConfigurableOptions
    {
        TOptions instance = Configuration
            .GetSection(ConfigurableOptions.GetConfigurationPath(typeof(TOptions)))
            .Get<TOptions>();
        return instance;
    }

    /// <summary>获取选项</summary>
    /// <typeparam name="TOptions">强类型选项类</typeparam>
    /// <param name="serviceProvider"></param>
    /// <returns>TOptions</returns>
    public static TOptions GetOptions<TOptions>(IServiceProvider serviceProvider = null) where TOptions : class, new()
    {
        IOptions<TOptions> service = GetService<IOptions<TOptions>>(serviceProvider ?? RootServices, false);
        return service?.Value;
    }

    /// <summary>获取选项</summary>
    /// <typeparam name="TOptions">强类型选项类</typeparam>
    /// <param name="serviceProvider"></param>
    /// <returns>TOptions</returns>
    public static TOptions GetOptionsMonitor<TOptions>(IServiceProvider serviceProvider = null)
        where TOptions : class, new()
    {
        IOptionsMonitor<TOptions> service =
            GetService<IOptionsMonitor<TOptions>>(serviceProvider ?? RootServices, false);
        return service?.CurrentValue;
    }

    /// <summary>获取选项</summary>
    /// <typeparam name="TOptions">强类型选项类</typeparam>
    /// <param name="serviceProvider"></param>
    /// <returns>TOptions</returns>
    public static TOptions GetOptionsSnapshot<TOptions>(IServiceProvider serviceProvider = null)
        where TOptions : class, new()
    {
        IOptionsSnapshot<TOptions> service = GetService<IOptionsSnapshot<TOptions>>(serviceProvider, false);
        return service?.Value;
    }

    #endregion
}

6.配置ApplicationSetup类,增加扩展方法

public static class ApplicationSetup
{
    public static void UseApplicationSetup(this WebApplication app)
    {
        app.Lifetime.ApplicationStarted.Register(() =>
        {
            App.IsRun = true;
        });

        app.Lifetime.ApplicationStopped.Register(() =>
        {
            App.IsRun = false;

            // 清除日志
            Log.CloseAndFlush();
        });
    }
}

7.在program.cs文件中注册服务
image

    .ConfigureAppConfiguration((hostingContext, config) =>
{
    hostingContext.Configuration.ConfigureApplication();
});

// 非依赖注入管道中获取所有服务(App类)
app.ConfigureApplication();
app.UseApplicationSetup();

8.在control层中使用
image

// 直接通过APP类获取以往需要依赖注入才能获得的对象
var roleServiceObjNew = App.GetService<IBaseService<Role, RoleVo>>(false);
var roleList = await roleServiceObjNew.Query();

// 直接通过APP类获取类似appsettings.json配置信息
RedisOptions redisOptions = App.GetOptions<RedisOptions>();
Console.WriteLine(JsonConvert.SerializeObject(redisOptions));
posted @ 2025-08-14 09:52  一切为了尚媛小姐  阅读(6)  评论(0)    收藏  举报