注意 互相關聯多使用介面註冊,所以可以 根據需要替換。
始於 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未完待續