Util应用框架核心(二)- 启动器
Util应用框架的启动初始化过程
基础用法查看Util服务配置,范例:
varbuilder=(args);().AddAop().AddSerilog().AddUtil();
注意其中调用了AddUtil方法.
AddUtil方法调用启动器进行初始化.
设计动机有些服务需要配置,但并不需要传递配置参数.
对于这类服务,我们希望自动完成配置,而不是手工调用AddXXX()方法.
Util项目需要一种自动执行特定初始化代码的方法.
Util启动时扫描全部程序集,找出特定代码块,并执行它们.
这些被自动执行的代码块,称为服务注册器.
Util启动器的设计和代码主要从NopCommerce吸收而来,并在项目实战中不断改进.
采用程序集扫描,是一种简单轻量的启动方式,不需要进行任何配置.
源码解析AddUtil扩展方法在IHostBuilder和IAppBuilder接口上扩展了AddUtil方法.
AddUtil方法调用Bootstrapper启动器的Start方法,扫描程序集执行服务注册器.
通常你不需要调用Bootstrapper类启动,使用AddUtil扩展方法会更简单.
///summary///主机生成器服务扩展////summarypublicstaticclassIHostBuilderExtensions{///summary///启动Util服务////summary///paramname="hostBuilder"主机生成器/parampublicstaticIHostBuilderAddUtil(thisIHostBuilderhostBuilder){(nameof(hostBuilder));varbootstrapper=newBootstrapper(hostBuilder);();returnhostBuilder;}///summary///启动Util服务////summary///paramname="appBuilder"应用生成器/parampublicstaticIAppBuilderAddUtil(thisIAppBuilderappBuilder){(nameof(appBuilder));varbootstrapper=newBootstrapper();();returnappBuilder;}}Bootstrapper启动器启动器使用类型查找器ITypeFinder找出所有启用的服务注册器IServiceRegistrar,并根据OrderId属性排序.
使用反射创建服务注册器实例,并将主机生成器IHostBuilder实例传递给它.
执行服务注册器实例的Register方法,完成服务初始化工作.
///summary///启动器////summarypublicclassBootstrapper{///summary///主机生成器////summaryprivatereadonlyIHostBuilder_hostBuilder;///summary///程序集查找器////summaryprivatereadonlyIAssemblyFinder_assemblyFinder;///summary///类型查找器////summaryprivatereadonlyITypeFinder_typeFinder;///summary///服务配置操作列表////summaryprivatereadonlyListAction_serviceActions;///summary///初始化启动器////summary///paramname="hostBuilder"主机生成器/parampublicBootstrapper(IHostBuilderhostBuilder){_hostBuilder=hostBuilder??thrownewArgumentNullException(nameof(hostBuilder));_assemblyFinder=newAppDomainAssemblyFinder{AssemblySkipPattern=};_typeFinder=newAppDomainTypeFinder(_assemblyFinder);_serviceActions=newListAction();}///summary///启动////summarypublicvirtualvoidStart(){ConfigureServices();ResolveServiceRegistrar();ExecuteServiceActions();}///summary///配置服务////summaryprotectedvirtualvoidConfigureServices(){_((context,services)={();(_assemblyFinder);(_typeFinder);});}///summary///解析服务注册器////summaryprotectedvirtualvoidResolveServiceRegistrar(){vartypes=_();varinstances=(type=(type)).Where(t=).OrderBy(t=).ToList();varcontext=newServiceContext(_hostBuilder,_assemblyFinder,_typeFinder);(t=_((context)));}///summary///执行延迟服务注册操作////summaryprotectedvirtualvoidExecuteServiceActions(){_(action=action?.Invoke());}}ITypeFinder类型查找器应用程序域类型查找器AppDomainTypeFinder使用程序集查找器IAssemblyFinder获取程序集列表.
并从程序集中查找指定接口的实现类型.
///summary///类型查找器////summarypublicinterfaceITypeFinder{///summary///查找类型列表////summary///typeparamname="T"查找类型/typeparamListTypeFindT();///summary///查找类型列表////summary///paramname="findType"查找类型/paramListTypeFind(TypefindType);}///summary///应用程序域类型查找器////summarypublicclassAppDomainTypeFinder:ITypeFinder{///summary///程序集查找器////summaryprivatereadonlyIAssemblyFinder_assemblyFinder;///summary///初始化应用程序域类型查找器////summary///paramname="assemblyFinder"程序集查找器/parampublicAppDomainTypeFinder(IAssemblyFinderassemblyFinder){_assemblyFinder=assemblyFinder??thrownewArgumentNullException(nameof(assemblyFinder));}///summary///查找类型列表////summary///typeparamname="T"查找类型/typeparampublicListTypeFindT(){returnFind(typeof(T));}///summary///获取程序集列表////summarypublicListAssemblyGetAssemblies(){return_();}///summary///查找类型列表////summary///paramname="findType"查找类型/parampublicListTypeFind(TypefindType){(findType,GetAssemblies()?.ToArray());}}IAssemblyFinder程序集查找器应用程序域程序集查找器AppDomainAssemblyFinder扫描当前应用程序域,获取全部程序集.
我们扫描程序集的目的,是希望从中获得服务注册器.
只有Util应用框架和你的项目相关的程序集中,才有可能包含服务注册器.
所以排除掉.Net和第三方类库程序集,将能大大提升扫描查找效率.
///summary///程序集查找器////summarypublicinterfaceIAssemblyFinder{///summary///程序集过滤模式////summarypublicstringAssemblySkipPattern{get;set;}///summary///查找程序集列表////summaryListAssemblyFind();}///summary///应用程序域程序集查找器////summarypublicclassAppDomainAssemblyFinder:IAssemblyFinder{///summary///程序集过滤模式////summarypublicstringAssemblySkipPattern{get;set;}///summary///程序集列表////summaryprivateListAssembly_assemblies;///summary///获取程序集列表////summarypublicListAssemblyFind(){if(_assemblies!=null)return_assemblies;_assemblies=newListAssembly();LoadAssemblies();foreach(()){if(IsSkip(assembly))continue;_(assembly);}return_assemblies;}///summary///加载引用但尚未调用的程序集列表到当前应用程序域////summaryprotectedvirtualvoidLoadAssemblies(){varcurrentDomainAssemblies=();foreach(stringfileinGetLoadAssemblyFiles())LoadAssembly(file,currentDomainAssemblies);}///summary///获取需要加载的程序集文件列表////summaryprotectedvirtualstring[]GetLoadAssemblyFiles(){(,"*.dll");}///summary///加载程序集到当前应用程序域////summaryprotectedvoidLoadAssembly(stringfile,Assembly[]currentDomainAssemblies){try{varassemblyName=(file);if(IsSkip())return;if((t===))return;(assemblyName);}catch(BadImageFormatException){}}///summary///是否过滤程序集////summaryprotectedboolIsSkip(stringassemblyName){varapplicationName=()?.GetName().Name;if((34;{applicationName}.PrecompiledViews"))returntrue;if((AssemblySkipPattern))returnfalse;(assemblyName,AssemblySkipPattern,|);}///summary///是否过滤程序集////summaryprivateboolIsSkip(Assemblyassembly){returnIsSkip();}}配置程序集过滤列表Util应用框架已经排除了引用的所有依赖库程序集.
但你的项目可能引用其它第三方类库,如果只引用了少量类库,影响非常小,但引用大量类库,则必须配置程序集过滤列表.
是启动器配置,AssemblySkipPattern属性提供了程序集过滤列表.
范例1
如果你想排除名为Demo的程序集.
+="|Demo";().AddUtil();
范例2
排除Demo开头的程序集,比如,
+="|^Demo";







