Abp 中 模組 載入及型別自動注入 原始碼學習筆記

weixin_30849591發表於2019-03-21

 注意 互相關聯多使用介面註冊,所以可以 根據需要替換。

始於 Startup.cs 中的 


通過  AddApplication 擴充套件方法新增   Abp支援

1
services.AddApplication<AbpWebSiteWebModule>(options => 2 { 3 options.UseAutofac(); 4 options.Configuration.UserSecretsAssembly = typeof(AbpWebSiteWebModule).Assembly; 5 });

內部,依次通過 AbpApplicationFactory、AbpApplicationWithExternalServiceProvider 註冊
     return AbpApplicationFactory.Create<TStartupModule>(services, optionsAction);
     return new AbpApplicationWithExternalServiceProvider(startupModuleType, services, optionsAction);
 services.AddSingleton<IAbpApplicationWithExternalServiceProvider>(this);
AbpApplicationWithExternalServiceProvider  同時繼承自 AbpApplicationBase 

AbpApplicationBase 構造初始化:

     services.AddSingleton<IAbpApplication>(this);
     services.AddSingleton<IModuleContainer>(this);

     services.AddCoreServices();   //新增日誌、本地化、選項服務
     services.AddCoreAbpServices(this, options); //新增IModuleLoader、IAssemblyFinder、ITypeFinder ,

           給模組新增應用程式生命週期入口,允許模組在應用程式啟動、關閉中執行操作。

           services.Configure<ModuleLifecycleOptions>(options =>
           {
              options.Contributors.Add<OnPreApplicationInitializationModuleLifecycleContributor>();
              options.Contributors.Add<OnApplicationInitializationModuleLifecycleContributor>();
              options.Contributors.Add<OnPostApplicationInitializationModuleLifecycleContributor>();
              options.Contributors.Add<OnApplicationShutdownModuleLifecycleContributor>();
           });

       然後呼叫IModuleLoader 載入模組: 載入思路是從啟動模組入手,遞迴遍歷所有依賴模組 被標記為[DependsOn]的模組

         依次執行  LoadModules -》GetDescriptors -》FillModules -》CreateModuleDescriptor -》SortByDependency  -》ConfigureServices

        最後一步是配置模組

 protected virtual void ConfigureServices(List<IAbpModuleDescriptor> modules, IServiceCollection services)
        {
            var context = new ServiceConfigurationContext(services);
            services.AddSingleton(context);

            foreach (var module in modules)
            {
                if (module.Instance is AbpModule abpModule)
                {
                    abpModule.ServiceConfigurationContext = context; //設定上下文
                }
            }

            //PreConfigureServices
            foreach (var module in modules.Where(m => m.Instance is IPreConfigureServices))
            {
                ((IPreConfigureServices)module.Instance).PreConfigureServices(context); //執行模組配置前操作
            }

            //ConfigureServices
            foreach (var module in modules)
            {
                if (module.Instance is AbpModule abpModule)
                {//允許模組設定不注入型別
                    if (!abpModule.SkipAutoServiceRegistration)
                    {
                        services.AddAssembly(module.Type.Assembly);  //載入並註冊模組中的型別  如 實現這些介面的會被自動註冊 ISingletonDependency ITransientDependency IScopedDependency
                    }
                }

                module.Instance.ConfigureServices(context);  //配置模組
            }

            //PostConfigureServices
            foreach (var module in modules.Where(m => m.Instance is IPostConfigureServices))
            {
                ((IPostConfigureServices)module.Instance).PostConfigureServices(context); //配置後操作
            }

            foreach (var module in modules)
            {
                if (module.Instance is AbpModule abpModule)
                {
                    abpModule.ServiceConfigurationContext = null; //清理上下文
                }
            }
        }

 

 

  



在  Configure 方法中初始化 AbpApplication ,

   public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
   {
       app.InitializeApplication();
   }

   請求 服務 ,並執行初始化操作

    public static void InitializeApplication([NotNull] this IApplicationBuilder app)
   {
         。。。。

         app.ApplicationServices.GetRequiredService<IAbpApplicationWithExternalServiceProvider>().Initialize(app.ApplicationServices);
    }

    開始 執行 AbpApplicationBase.InitializeModules();

using (var scope = ServiceProvider.CreateScope())
{
scope.ServiceProvider
.GetRequiredService<IModuleManager>()
.InitializeModules(new ApplicationInitializationContext(scope.ServiceProvider));
}

  通過 IModuleManager  初始化模組

public void InitializeModules(ApplicationInitializationContext context)
{
LogListOfModules();

foreach (var Contributor in _lifecycleContributors)
{
foreach (var module in _moduleContainer.Modules)
{
Contributor.Initialize(context, module.Instance);
}
}

_logger.LogInformation("Initialized all modules.");
}

 

 

 

2、模組程式集類庫註冊 機制

  public static IServiceCollection AddAssembly(this IServiceCollection services, Assembly assembly)
        {
            foreach (var registrar in services.GetConventionalRegistrars())
            {
                registrar.AddAssembly(services, assembly);
            }

            return services;
        }
這裡關鍵是 ConventionalRegistrarBase 用來處理那些型別是可以被註冊的
1、過濾型別 必須是 類
var types=
AssemblyHelper.GetAllTypes(assembly) .Where(type => type != null && type.IsClass && !type.IsAbstract && !type.IsGenericType)  
foreach (var type in types)       {     AddType(services, type);        }
  估計本部分還在改進中
  //TODO: Make DefaultConventionalRegistrar extensible, so we can only define GetLifeTimeOrNull to contribute to the convention. This can be more performant!
1、子類 DefaultConventionalRegistrar 重寫方法
public override void AddType(IServiceCollection services, Type type)
    (1) DisableConventionalRegistrationAttribute 如果設定了這個 屬性,則跳過
(2) 嘗試取DependencyAttribute 如果有,則為生存期
或者 GetLifeTimeOrNull取得他的生存期
ISingletonDependency IScopedDependency ITransientDependency 直接註冊,或者
2、AbpAspNetCoreMvcConventionalRegistrar 繼承自 DefaultConventionalRegistrar  重寫了 GetServiceLifetimeFromClassHierarcy 方法  增加了三個介面

         if (IsController(type) ||  IsPageModel(type) ||IsViewComponent(type)){return ServiceLifetime.Transient;}


 


private static bool IsPageModel(Type type)
{
return typeof(PageModel).IsAssignableFrom(type) || type.IsDefined(typeof(PageModelAttribute), true);
}

private static bool IsController(Type type)
{
return typeof(Controller).IsAssignableFrom(type) || type.IsDefined(typeof(ControllerAttribute), true);
}

private static bool IsViewComponent(Type type)
{
return typeof(ViewComponent).IsAssignableFrom(type) || type.IsDefined(typeof(ViewComponentAttribute), true);
}



如果都符合條件,則進行註冊

    //查詢這個型別暴漏的所有服務!,每一個服務根據依賴情況進行替換、新增

      foreach (var serviceType in AutoRegistrationHelper.GetExposedServices(services, type))

     //查詢過程
   private static IEnumerable<Type> GetDefaultExposedServices(IServiceCollection services, Type type)
        {
            var serviceTypes = new List<Type>();

            serviceTypes.Add(type);

            foreach (var interfaceType in type.GetTypeInfo().GetInterfaces())
            {
                var interfaceName = interfaceType.Name;

                if (interfaceName.StartsWith("I"))
                {
                    interfaceName = interfaceName.Right(interfaceName.Length - 1);
                }

                if (type.Name.EndsWith(interfaceName))
                {
                    serviceTypes.Add(interfaceType);
                }
            }

            var exposeActions = services.GetExposingActionList();
            if (exposeActions.Any())
            {
                var args = new OnServiceExposingContext(type, serviceTypes);
                foreach (var action in services.GetExposingActionList())
                {
                    action(args);
                }
            }

            return serviceTypes;
        }

 

 

 

 

 ----w未完待續

 

轉載於:https://www.cnblogs.com/abin30/p/10572087.html

相關文章