首页 > 编程语言 >Adnc 源码解析

Adnc 源码解析

时间:2024-07-12 12:31:04浏览次数:9  
标签:string serviceInfo 源码 startAssembly Adnc var 解析 public

先看 Adnc.Demo.Usr.Api 解决方案

 var startAssembly = System.Reflection.Assembly.GetExecutingAssembly();
 var startAssemblyName = startAssembly.GetName().Name ?? string.Empty;
 var lastName = startAssemblyName.Split('.').Last();
 var migrationsAssemblyName = startAssemblyName.Replace($".{lastName}", ".Repository");
 var serviceInfo = ServiceInfo.CreateInstance(startAssembly, migrationsAssemblyName); 

 

上面代码 是构建   Adnc.Demo.Usr.Api  服务信息

namespace Adnc.Shared.WebApi;

public class ServiceInfo : IServiceInfo
{
    private static ServiceInfo? _instance = null;
    private static readonly object _lockObj = new();

    public string Id { get; private set; } = string.Empty;
    public string ServiceName { get; private set; } = string.Empty;
    public string CorsPolicy { get; set; } = string.Empty;
    public string ShortName { get; private set; } = string.Empty;
    public string RelativeRootPath { get; private set; } = string.Empty;
    public string Version { get; private set; } = string.Empty;
    public string Description { get; private set; } = string.Empty;
    public Assembly StartAssembly { get; private set; } = default!;
    public string MigrationsAssemblyName { get; private set; } = string.Empty;

    private ServiceInfo()
    {
    }

    public static ServiceInfo CreateInstance(Assembly startAssembly, string? migrationsAssemblyName = null)
    {
        if (_instance is not null)
            return _instance;

        lock (_lockObj)
        {
            if (_instance is not null)
                return _instance;

            if (startAssembly is null)
                startAssembly = Assembly.GetEntryAssembly() ?? throw new NullReferenceException(nameof(startAssembly));

            var attribute = startAssembly.GetCustomAttribute<AssemblyDescriptionAttribute>();
            var description = attribute is null ? string.Empty : attribute.Description;
            var version = startAssembly.GetName().Version ?? throw new NullReferenceException("startAssembly.GetName().Version");
            var startAssemblyName = startAssembly.GetName().Name ?? string.Empty;
            var serviceName = startAssemblyName.Replace(".", "-").ToLower();
            var ticks = DateTime.Now.GetTotalMilliseconds().ToLong();
            var ticksHex = Convert.ToString(ticks, 16);
            var envName = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")?.ToLower();
            var serviceId = envName switch
            {
                "development" => $"{serviceName}-dev-{ticksHex}",
                "test" => $"{serviceName}-test-{ticksHex}",
                "staging" => $"{serviceName}-stag-{ticksHex}",
                "production" => $"{serviceName}-{ticksHex}",
                _ => throw new NullReferenceException("ASPNETCORE_ENVIRONMENT")
            };

            var names = startAssemblyName.Split(".");
            migrationsAssemblyName ??= startAssemblyName.Replace($".{names.Last()}", ".Migrations");
            _instance = new ServiceInfo
            {
                Id = serviceId,
                ServiceName = serviceName,
                ShortName = $"{names[^2]}-{names[^1]}".ToLower(),
                RelativeRootPath = $"{names[^2]}/{names[^1]}".ToLower(),
                CorsPolicy = "default",
                StartAssembly = startAssembly,
                Description = description,
                Version = $"{version.Major}.{version.Minor}.{version.Build}.{version.Revision}",
                MigrationsAssemblyName = migrationsAssemblyName
            };
        }
        return _instance;
    }

    public static ServiceInfo GetInstance()
    {
        if (_instance is null)
            throw new NullReferenceException(nameof(ServiceInfo));

        return _instance;
    }
}

  

上面使用得是单例 模式 

注意 这里的 代码   public Assembly StartAssembly { get; private set; } = default!;

StartAssembly  后面需要 用它反射

接下来 这行代码 

var app = WebApplication.CreateBuilder(args).ConfigureAdncDefault(serviceInfo).Build();

调用 ConfigureAdncDefault(serviceInfo) 

这是一个扩展方法 在 Adnc.Shared.WebApi  解决方案中

 public static WebApplicationBuilder ConfigureAdncDefault(this WebApplicationBuilder builder, IServiceInfo serviceInfo)

{

   builder.Services.AddAdnc(serviceInfo);

}

调用了 AddAdnc(serviceInfo) 扩展方法

 

public static class ServiceCollectionExtension
{
    /// <summary>
    ///  统一注册Adnc.WebApi通用服务
    /// </summary>
    /// <param name="services"></param>
    /// <param name="startupAssembly"></param>
    /// <returns></returns>
    /// <exception cref="ArgumentNullException"></exception>
    /// <exception cref="NullReferenceException"></exception>
    public static IServiceCollection AddAdnc(this IServiceCollection services, IServiceInfo serviceInfo)
    {
        if (serviceInfo?.StartAssembly is null)
            throw new ArgumentNullException(nameof(serviceInfo));
        var webApiRegistarType = serviceInfo.StartAssembly.ExportedTypes.FirstOrDefault(m => m.IsAssignableTo(typeof(IDependencyRegistrar)) && m.IsAssignableTo(typeof(AbstractWebApiDependencyRegistrar)) && m.IsNotAbstractClass(true));
        if (webApiRegistarType is null)
            throw new NullReferenceException(nameof(IDependencyRegistrar));

        if (Activator.CreateInstance(webApiRegistarType, services) is not IDependencyRegistrar webapiRegistar)
            throw new NullReferenceException(nameof(webapiRegistar));

        webapiRegistar.AddAdnc();

        return services;
    }
} 

 

上面 红色代码  serviceInfo.StartAssembly 通过他反射

创建了 子类  Activator.CreateInstance(webApiRegistarType, services) is not IDependencyRegistrar webapiRegistar

子类也就是   Adnc.Demo.Usr.Api 解决方法中得  UsrWebApiDependencyRegistrar

using Adnc.Demo.Usr.Api.Authentication;
using Adnc.Demo.Usr.Api.Authorization;
using Adnc.Shared.WebApi.Registrar;

namespace Adnc.Demo.Usr.Api;

public sealed class UsrWebApiDependencyRegistrar : AbstractWebApiDependencyRegistrar
{
   
    public UsrWebApiDependencyRegistrar(IServiceCollection services)
        : base(services)
    {
    }

    public UsrWebApiDependencyRegistrar(IApplicationBuilder app)
        : base(app)
    {
    }

    public override void AddAdnc()
    {
        AddWebApiDefault<BearerAuthenticationLocalProcessor, PermissionLocalHandler>();
        AddHealthChecks(true, true, true, false);
        Services.AddGrpc();
    }

    public override void UseAdnc()
    {
        UseWebApiDefault(endpointRoute: endpoint =>
        {
            endpoint.MapGrpcService<Grpc.AuthGrpcServer>();
            endpoint.MapGrpcService<Grpc.UsrGrpcServer>();
        });
    }
}

  

子类 重写了父类得 AddAdnc() 方法 调用了 父类AbstractWebApiDependencyRegistrar 中得 AddWebApiDefault<BearerAuthenticationLocalProcessor, PermissionLocalHandler>(); 方法 也就是 

 /// <summary>
 /// 注册Webapi通用的服务
 /// </summary>
 /// <typeparam name="TAuthenticationProcessor"><see cref="AbstractAuthenticationProcessor"/></typeparam>
 /// <typeparam name="TAuthorizationHandler"><see cref="AbstractPermissionHandler"/></typeparam>
 protected virtual void AddWebApiDefault<TAuthenticationProcessor, TAuthorizationHandler>()
     where TAuthenticationProcessor : AbstractAuthenticationProcessor
     where TAuthorizationHandler : AbstractPermissionHandler
 {

     Services.AddControllers();
   

     Services
         .AddHttpContextAccessor()
         .AddMemoryCache();
     Configure();
     AddControllers();
     AddAuthentication<TAuthenticationProcessor>();
     AddAuthorization<TAuthorizationHandler>();
     AddCors();
     var enableSwaggerUI = Configuration.GetValue(NodeConsts.SwaggerUI_Enable, true);
     if(enableSwaggerUI)
     {
         AddSwaggerGen();
         AddMiniProfiler();
     }
     AddApplicationServices();
 }

  

父类中的 方法 调用了 AddApplicationServices(); 方法

这个方法

namespace Adnc.Shared.WebApi.Registrar;

public abstract partial class AbstractWebApiDependencyRegistrar
{
    /// <summary>
    /// 注册Application层服务
    /// </summary>
    protected virtual void AddApplicationServices()
    {
 
        var appAssembly = ServiceInfo.GetApplicationAssembly();
       
        if (appAssembly is not null)
        {
            var applicationRegistrarType = appAssembly.ExportedTypes.FirstOrDefault(m => m.IsAssignableTo(typeof(IDependencyRegistrar)) && !m.IsAssignableTo(typeof(AbstractWebApiDependencyRegistrar)) && m.IsNotAbstractClass(true));
            if (applicationRegistrarType is not null)
            {
                var applicationRegistrar = Activator.CreateInstance(applicationRegistrarType, Services) as IDependencyRegistrar;
                applicationRegistrar?.AddAdnc();
            }
        }
    }
}

 

这段代码 ServiceInfo.GetApplicationAssembly(); 获取了 Adnc.Shared.Application 程序集

using Adnc.Infra.Consul.Configuration;

namespace Adnc.Shared.WebApi
{
    public static class ServiceInfoExtension
    {
        private static readonly object lockObj = new();
        private static Assembly? appAssembly;

        /// <summary>
        /// 获取WebApiAssembly程序集
        /// </summary>
        /// <returns></returns>
        public static Assembly GetWebApiAssembly(this IServiceInfo serviceInfo) => serviceInfo.StartAssembly;

        /// <summary>
        /// 获取Application程序集
        /// </summary>
        /// <returns></returns>
        public static Assembly GetApplicationAssembly(this IServiceInfo serviceInfo)
        {
            if (appAssembly is null)
            {
                lock (lockObj)
                {
                    if (appAssembly is null)
                    {
                        Assembly startAssembly = serviceInfo.StartAssembly ?? throw new NullReferenceException(nameof(serviceInfo.StartAssembly));
                        string startAssemblyFullName = startAssembly.FullName ?? throw new NullReferenceException(nameof(startAssembly.FullName));
                        string startAssemblyName = startAssembly.GetName().Name ?? string.Empty;
                        string lastName = startAssemblyName.Split(".").Last();
                        string appAssemblyFullName = startAssemblyFullName.Replace($".{lastName}", ".Application");
                        appAssembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(x => x.FullName == appAssemblyFullName);
                        if (appAssembly is null)
                        {
                            appAssembly = startAssembly;
                            //appAssembly = Assembly.Load(appAssemblyName);
                            //var appAssemblyPath = serviceInfo.AssemblyLocation.Replace(".WebApi.dll", ".Application.dll");
                            ///appAssembly = Assembly.LoadFrom(appAssemblyPath);
                        }
                    }
                }
            }
            return appAssembly;
        }

        /// <summary>
        /// 获取导航首页内容
        /// </summary>
        /// <param name="serviceInfo"></param>
        /// <param name="app"></param>
        /// <returns></returns>
        public static string GetDefaultPageContent(this IServiceInfo serviceInfo, IServiceProvider serviceProvider)
        {
            var swaggerUrl = $"/{serviceInfo.RelativeRootPath}/index.html";
            var consulOptions = serviceProvider.GetRequiredService<IOptions<ConsulOptions>>();
            var healthCheckUrl = consulOptions?.Value?.HealthCheckUrl ?? $"/{serviceInfo.RelativeRootPath}/health-24b01005-a76a-4b3b-8fb1-5e0f2e9564fb";
            var envName = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
            var content = $"<div align='center'><a href='https://github.com/alphayu/adnc' target='_blank'><img src='https://aspdotnetcore.net/wp-content/uploads/2023/04/adnc-topics.png'/></a><br>" +
                $"ASPNETCORE_ENVIRONMENT = {envName} <br> " +
                $"Version = {serviceInfo.Version} <br> " +
                $"ServiceName = {serviceInfo.ServiceName} <br> " +
                $"ShortName = {serviceInfo.ShortName} <br> " +
                $"RelativeRootPath = {serviceInfo.RelativeRootPath} <br> " +
                $"<br><a href='{swaggerUrl}'>swagger UI</a> | <a href='{healthCheckUrl}'>healthy checking</a><br>" +
                $"<br>{DateTime.Now}</div>";
            return content;
        }
    }
}

  

这段代码

 string appAssemblyFullName = startAssemblyFullName.Replace($".{lastName}", ".Application");
 appAssembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(x => x.FullName == appAssemblyFullName);
是获取 Adnc.Shared.Application 程序集

 

这个方法通过反射 构造了 DependencyRegistrar 对象 强调 一下 这是是对 Adnc.Demo.Usr.Application 中的 DependencyRegistrar 构造 对象 

namespace Adnc.Demo.Usr.Application;

public sealed class DependencyRegistrar : AbstractApplicationDependencyRegistrar
{
    public override Assembly ApplicationLayerAssembly => Assembly.GetExecutingAssembly();

    public override Assembly ContractsLayerAssembly => typeof(IUserAppService).Assembly;

    public override Assembly RepositoryOrDomainLayerAssembly => typeof(EntityInfo).Assembly;

    public DependencyRegistrar(IServiceCollection services) : base(services)
    {
    }

    public override void AddAdnc() => AddApplicaitonDefault();
}
Adnc.Demo.Usr.Application 解决方案 DependencyRegistrar 类 重写了 父类方法 
public override void AddAdnc() => AddApplicaitonDefault();
该方法  AddApplicaitonDefault() 在 Adnc.Shared.Application 解决方案
/// <summary>
/// 注册adnc.application通用服务
/// </summary>
protected virtual void AddApplicaitonDefault()
{
    Services
        .AddValidatorsFromAssembly(ContractsLayerAssembly, ServiceLifetime.Scoped)
        .AddAdncInfraAutoMapper(ApplicationLayerAssembly)
        .AddAdncInfraYitterIdGenerater(RedisSection)
        .AddAdncInfraConsul(ConsulSection)
        .AddAdncInfraDapper();

    AddApplicationSharedServices();
    AddAppliactionSerivcesWithInterceptors();
    AddApplicaitonHostedServices();
    AddEfCoreContextWithRepositories();
    AddMongoContextWithRepositries();
    AddRedisCaching();
    AddBloomFilters();
}

  

这里 说明 AddEfCoreContextWithRepositories(); 这个方法 是注册 EF

using Adnc.Infra.Repository.EfCore.MySql.Configurations;
using Adnc.Infra.Repository.Mongo;
using Adnc.Infra.Repository.Mongo.Configuration;
using Adnc.Infra.Repository.Mongo.Extensions;
using Microsoft.EntityFrameworkCore;

namespace Adnc.Shared.Application.Registrar;

public abstract partial class AbstractApplicationDependencyRegistrar
{
    /// <summary>
    /// 注册EFCoreContext与仓储
    /// </summary>
    protected virtual void AddEfCoreContextWithRepositories()
    {
        var serviceType = typeof(IEntityInfo);
        var implType = RepositoryOrDomainLayerAssembly.ExportedTypes.FirstOrDefault(type => type.IsAssignableTo(serviceType) && type.IsNotAbstractClass(true));
        if (implType is null)
            throw new NotImplementedException(nameof(IEntityInfo));
        else
            Services.AddScoped(serviceType, implType);

        AddEfCoreContext();
    }

    /// <summary>
    /// 注册EFCoreContext
    /// </summary>
    protected virtual void AddEfCoreContext()
    {
        var serviceInfo = Services.GetServiceInfo();
        var mysqlConfig = MysqlSection.Get<MysqlOptions>();
        var serverVersion = new MariaDbServerVersion(new Version(10, 5, 4));
        Services.AddAdncInfraEfCoreMySql(options =>
        {
            options.UseLowerCaseNamingConvention();
            options.UseMySql(mysqlConfig.ConnectionString, serverVersion, optionsBuilder =>
            {
                optionsBuilder.MinBatchSize(4)
                                        .MigrationsAssembly(serviceInfo.MigrationsAssemblyName)
                                        .UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery);
            });

            //if (this.IsDevelopment())
            //{
            //    //options.AddInterceptors(new DefaultDbCommandInterceptor())
            //    options.LogTo(Console.WriteLine, LogLevel.Information)
            //                .EnableSensitiveDataLogging()
            //                .EnableDetailedErrors();
            //}
            //替换默认查询sql生成器,如果通过mycat中间件实现读写分离需要替换默认SQL工厂。
            //options.ReplaceService<IQuerySqlGeneratorFactory, AdncMySqlQuerySqlGeneratorFactory>();
        });
    }

    /// <summary>
    /// 注册MongoContext与仓储
    /// </summary>
    protected virtual void AddMongoContextWithRepositries(Action<IServiceCollection>? action = null)
    {
        action?.Invoke(Services);

        var mongoConfig = MongoDbSection.Get<MongoOptions>();
        Services.AddAdncInfraMongo<MongoContext>(options =>
        {
            options.ConnectionString = mongoConfig.ConnectionString;
            options.PluralizeCollectionNames = mongoConfig.PluralizeCollectionNames;
            options.CollectionNamingConvention = (NamingConvention)mongoConfig.CollectionNamingConvention;
        });
    }
}

  

其中 Services.AddAdncInfraEfCoreMySql扩展方法  调用得 是   Adnc.Infra.Repository.EfCore.MySql 解决方案 注册了 仓储 这里

using Adnc.Infra.Repository.EfCore.MySql;
using Adnc.Infra.Repository.EfCore.MySql.Transaction;

namespace Microsoft.Extensions.DependencyInjection;

public static class ServiceCollectionExtension
{
    public static IServiceCollection AddAdncInfraEfCoreMySql(this IServiceCollection services, Action<DbContextOptionsBuilder> optionsBuilder)
    {
        if (services.HasRegistered(nameof(AddAdncInfraEfCoreMySql)))
            return services;

        services.TryAddScoped<IUnitOfWork, MySqlUnitOfWork<MySqlDbContext>>();
        services.TryAddScoped(typeof(IEfRepository<>), typeof(EfRepository<>));
        services.TryAddScoped(typeof(IEfBasicRepository<>), typeof(EfBasicRepository<>));
        services.AddDbContext<DbContext, MySqlDbContext>(optionsBuilder);

        return services;
    }
}

  

这篇 分析了

Adnc.Demo.Usr.Api -----(ConfigureAdncDefault(serviceInfo))---------> Adnc.Shared.WebApi --------  AddAdnc 反射获取子类 子类重写 AddAdnc  调用了父类 

AddWebApiDefault.AddApplicationServices 反射出  Adnc.Shared.Application------->

Adnc.Shared.Application ----- (AbstractApplicationDependencyRegistrar.AddApplicaitonDefault.AddEfCoreContextWithRepositories) ----->

Adnc.Infra.Repository.EfCore.MySql

 

就是 依次 往上调用 

 

  

 

标签:string,serviceInfo,源码,startAssembly,Adnc,var,解析,public
From: https://www.cnblogs.com/yyxone/p/18298101

相关文章

  • 网桥与以太网交换机:功能与区别解析
    在传统的共享式局域网中,所有站点共享一个公共的传输媒体。随着局域网规模的扩大、网络中站点数目的不断增加,这样的网络通信负载加重,网络效率急剧下降。随着技术的发展、交换技术的成熟和成本的降低,具有更高性能的交换式局域网在有线领域已完全取代了传统的共享式局域网。本......
  • Redis数据结构—跳跃表 skiplist 实现源码分析
    Redis是一个开源的内存数据结构存储系统,它可以用作数据库、缓存和消息中间件。Redis的数据结构非常丰富,其中跳跃表(skiplist)是一种重要的数据结构,它被用来实现有序集合(sortedsets)。跳跃表是一种概率型数据结构,它通过多层链表来实现快速的查找操作。跳跃表的结构类似于多层索引,......
  • 最新AI一站式系统源码-ChatGPT商业版系统源码,支持自定义AI智能体应用、AI绘画、AI视频
     一、前言人工智能语言模型和AI绘画在多个领域都有广泛的应用.....SparkAi创作系统是一款基于ChatGPT和Midjourney开发的智能问答和绘画系统,提供一站式AIB/C端解决方案,涵盖AI大模型提问、AI绘画、AI视频、文档分析、图像识别和理解、TTS&语音识别、AI换脸等多项功能。......
  • 4-LinkedList底层结构和源码分析
    4-LinkedList底层结构和源码分析介绍汇总:LinkedList的全面说明LinkedList的底层操作机制LinkedList的运行重要步骤ArrayList和LinkedList比较1-LinkedList的全面说明LinkedList底层实现了双向链表和双端队列特点可以添加任意元素(元素可以重复),包括null线程不安全,......
  • 法法易解析液冷充电枪的关键技术体系
    随着时代的发展,科学技术也在不断发展壮大,目前,国家也拥有完善的电力基础,但是随着大功率充电的发展,不可避免的对国家电网的电力供应提出更高的要求。如何配合电动汽车的充电需求和现有基础电力设施一同使用,这就需要考虑清楚液冷充电枪的各个方面,以求防患于未然安全隐患。这是因为......
  • 毕业设计-基于Springboot+Vue的招生管理系统的设计与实现(源码+LW+包运行)
    源码获取:https://download.csdn.net/download/u011832806/89456200基于SpringBoot+Vue的招生管理系统开发语言:Java数据库:MySQL技术:SpringBoot+MyBatis+Vue.js工具:IDEA/Ecilpse、Navicat、Maven系统演示视频:链接:https://pan.baidu.com/s/1GwKRBbuwMiZmnxkvRN9VJg?pwd=sb......
  • 毕业设计-基于Springboot+Vue的致远汽车租赁系统的设计与实现(源码+LW+包运行)
    源码获取:https://download.csdn.net/download/u011832806/89456206基于SpringBoot+Vue的致远汽车租赁系统开发语言:Java数据库:MySQL技术:SpringBoot+MyBatis+Vue.js工具:IDEA/Ecilpse、Navicat、Maven系统演示视频:链接:https://pan.baidu.com/s/1IHfaizhpMI1q750DBZ1enA?pw......
  • 毕业设计-基于Springboot+Vue的智慧外贸平台的设计与实现(源码+LW+包运行)
    源码获取:https://download.csdn.net/download/u011832806/89456212基于SpringBoot+Vue的智慧外贸平台开发语言:Java数据库:MySQL技术:SpringBoot+MyBatis+Vue.js工具:IDEA/Ecilpse、Navicat、Maven系统演示视频:链接:https://pan.baidu.com/s/1PnEjpc6IXOgPmYxluTOr2g?pwd=kv......
  • Linux jq 命令讲解与实战操作(json字符串解析工具)
    Linuxjq命令讲解与实战操作(json字符串解析工具)大数据老司机2023-08-0914:23 一、概述jq 是一个强大的命令行工具,用于处理 JSON 格式的数据。它可以帮助你查询、过滤、修改和处理 JSON 数据,使得在命令行环境下处理 JSON 变得非常方便。GitHub地......
  • 【项目实战】深入解析HTTP状态码:401 Unauthorized
    在网络通信过程中,HTTP状态码对于服务器和客户端之间的信息交流起着至关重要的作用。其中,401Unauthorized(未授权)是一个非常关键的状态码,它涉及到安全认证的方面。本文将详细介绍401状态码,分析其原因,并提供针对性的解决方案,以帮助开发者和用户更好地理解和处理这种情况。1.......