<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Util應(yīng)用框架核心(二) - 啟動(dòng)器

      本節(jié)介紹 Util 項(xiàng)目啟動(dòng)初始化過程.

      文章分為多個(gè)小節(jié),如果對(duì)設(shè)計(jì)原理不感興趣,只需閱讀基礎(chǔ)用法部分即可.

      基礎(chǔ)用法

      查看 Util 服務(wù)配置,范例:

      var builder = WebApplication.CreateBuilder( args );
      builder.AsBuild()
        .AddAop()
        .AddSerilog()
        .AddUtil();
      

      注意其中調(diào)用了 AddUtil 方法.

      AddUtil 方法調(diào)用啟動(dòng)器進(jìn)行初始化.

      設(shè)計(jì)動(dòng)機(jī)

      有些服務(wù)需要配置,但并不需要傳遞配置參數(shù).

      對(duì)于這類服務(wù),我們希望自動(dòng)完成配置,而不是手工調(diào)用 AddXXX() 方法.

      Util項(xiàng)目需要一種自動(dòng)執(zhí)行特定初始化代碼的方法.

      Util啟動(dòng)時(shí)掃描全部程序集,找出特定代碼塊,并執(zhí)行它們.

      這些被自動(dòng)執(zhí)行的代碼塊,稱為服務(wù)注冊器.

      Util 啟動(dòng)器的設(shè)計(jì)和代碼主要從 NopCommerce 吸收而來,并在項(xiàng)目實(shí)戰(zhàn)中不斷改進(jìn).

      采用程序集掃描,是一種簡單輕量的啟動(dòng)方式,不需要進(jìn)行任何配置.

      源碼解析

      AddUtil 擴(kuò)展方法

      IHostBuilderIAppBuilder 接口上擴(kuò)展了 AddUtil 方法.

      AddUtil 方法調(diào)用 Bootstrapper 啟動(dòng)器的 Start 方法,掃描程序集執(zhí)行服務(wù)注冊器.

      通常你不需要調(diào)用 Bootstrapper 類啟動(dòng),使用 AddUtil 擴(kuò)展方法會(huì)更簡單.

      /// <summary>
      /// 主機(jī)生成器服務(wù)擴(kuò)展
      /// </summary>
      public static class IHostBuilderExtensions {
          /// <summary>
          /// 啟動(dòng)Util服務(wù) 
          /// </summary>
          /// <param name="hostBuilder">主機(jī)生成器</param>
          public static IHostBuilder AddUtil( this IHostBuilder hostBuilder ) {
              hostBuilder.CheckNull( nameof( hostBuilder ) );
              var bootstrapper = new Bootstrapper( hostBuilder );
              bootstrapper.Start();
              return hostBuilder;
          }
      
          /// <summary>
          /// 啟動(dòng)Util服務(wù) 
          /// </summary>
          /// <param name="appBuilder">應(yīng)用生成器</param>
          public static IAppBuilder AddUtil( this IAppBuilder appBuilder ) {
              appBuilder.CheckNull( nameof( appBuilder ) );
              var bootstrapper = new Bootstrapper( appBuilder.Host );
              bootstrapper.Start();
              return appBuilder;
          }
      }
      

      Bootstrapper 啟動(dòng)器

      啟動(dòng)器使用類型查找器 ITypeFinder 找出所有啟用的服務(wù)注冊器 IServiceRegistrar,并根據(jù) OrderId 屬性排序.

      使用反射創(chuàng)建服務(wù)注冊器實(shí)例,并將主機(jī)生成器 IHostBuilder 實(shí)例傳遞給它.

      執(zhí)行服務(wù)注冊器實(shí)例的 Register 方法,完成服務(wù)初始化工作.

      /// <summary>
      /// 啟動(dòng)器
      /// </summary>
      public class Bootstrapper {
          /// <summary>
          /// 主機(jī)生成器
          /// </summary>
          private readonly IHostBuilder _hostBuilder;
          /// <summary>
          /// 程序集查找器
          /// </summary>
          private readonly IAssemblyFinder _assemblyFinder;
          /// <summary>
          /// 類型查找器
          /// </summary>
          private readonly ITypeFinder _typeFinder;
          /// <summary>
          /// 服務(wù)配置操作列表
          /// </summary>
          private readonly List<Action> _serviceActions;
      
          /// <summary>
          /// 初始化啟動(dòng)器
          /// </summary>
          /// <param name="hostBuilder">主機(jī)生成器</param>
          public Bootstrapper( IHostBuilder hostBuilder ) {
              _hostBuilder = hostBuilder ?? throw new ArgumentNullException( nameof( hostBuilder ) );
              _assemblyFinder = new AppDomainAssemblyFinder { AssemblySkipPattern = BootstrapperConfig.AssemblySkipPattern };
              _typeFinder = new AppDomainTypeFinder( _assemblyFinder );
              _serviceActions = new List<Action>();
          }
      
          /// <summary>
          /// 啟動(dòng)
          /// </summary>
          public virtual void Start() {
              ConfigureServices();
              ResolveServiceRegistrar();
              ExecuteServiceActions();
          }
      
          /// <summary>
          /// 配置服務(wù)
          /// </summary>
          protected virtual void ConfigureServices() {
              _hostBuilder.ConfigureServices( ( context, services ) => {
                  Util.Helpers.Config.SetConfiguration( context.Configuration );
                  services.TryAddSingleton( _assemblyFinder );
                  services.TryAddSingleton( _typeFinder );
              } );
          }
      
          /// <summary>
          /// 解析服務(wù)注冊器
          /// </summary>
          protected virtual void ResolveServiceRegistrar() {
              var types = _typeFinder.Find<IServiceRegistrar>();
              var instances = types.Select( type => Reflection.CreateInstance<IServiceRegistrar>( type ) ).Where( t => t.Enabled ).OrderBy( t => t.OrderId ).ToList();
              var context = new ServiceContext( _hostBuilder, _assemblyFinder, _typeFinder );
              instances.ForEach( t => _serviceActions.Add( t.Register( context ) ) );
          }
      
          /// <summary>
          /// 執(zhí)行延遲服務(wù)注冊操作
          /// </summary>
          protected virtual void ExecuteServiceActions() {
              _serviceActions.ForEach( action => action?.Invoke() );
          }
      }
      

      ITypeFinder 類型查找器

      應(yīng)用程序域類型查找器 AppDomainTypeFinder 使用程序集查找器 IAssemblyFinder 獲取程序集列表.

      并從程序集中查找指定接口的實(shí)現(xiàn)類型.

      /// <summary>
      /// 類型查找器
      /// </summary>
      public interface ITypeFinder {
          /// <summary>
          /// 查找類型列表
          /// </summary>
          /// <typeparam name="T">查找類型</typeparam>
          List<Type> Find<T>();
          /// <summary>
          /// 查找類型列表
          /// </summary>
          /// <param name="findType">查找類型</param>
          List<Type> Find( Type findType );
      }
      
      /// <summary>
      /// 應(yīng)用程序域類型查找器
      /// </summary>
      public class AppDomainTypeFinder : ITypeFinder {
          /// <summary>
          /// 程序集查找器
          /// </summary>
          private readonly IAssemblyFinder _assemblyFinder;
      
          /// <summary>
          /// 初始化應(yīng)用程序域類型查找器
          /// </summary>
          /// <param name="assemblyFinder">程序集查找器</param>
          public AppDomainTypeFinder( IAssemblyFinder assemblyFinder ) {
              _assemblyFinder = assemblyFinder ?? throw new ArgumentNullException( nameof( assemblyFinder ) );
          }
      
          /// <summary>
          /// 查找類型列表
          /// </summary>
          /// <typeparam name="T">查找類型</typeparam>
          public List<Type> Find<T>() {
              return Find( typeof( T ) );
          }
      
          /// <summary>
          /// 獲取程序集列表
          /// </summary>
          public List<Assembly> GetAssemblies() {
              return _assemblyFinder.Find();
          }
      
          /// <summary>
          /// 查找類型列表
          /// </summary>
          /// <param name="findType">查找類型</param>
          public List<Type> Find( Type findType ) {
              return Reflection.FindImplementTypes( findType, GetAssemblies()?.ToArray() );
          }
      }
      

      IAssemblyFinder 程序集查找器

      應(yīng)用程序域程序集查找器 AppDomainAssemblyFinder 掃描當(dāng)前應(yīng)用程序域,獲取全部程序集.

      值得注意的是,如果在應(yīng)用程序域所有程序集中進(jìn)行查找,必定效率十分低下,啟動(dòng)將異常緩慢.

      我們掃描程序集的目的,是希望從中獲得服務(wù)注冊器.

      只有Util應(yīng)用框架和你的項(xiàng)目相關(guān)的程序集中,才有可能包含服務(wù)注冊器.

      所以排除掉 .Net 和第三方類庫程序集,將能大大提升掃描查找效率.

      /// <summary>
      /// 程序集查找器
      /// </summary>
      public interface IAssemblyFinder {
          /// <summary>
          /// 程序集過濾模式
          /// </summary>
          public string AssemblySkipPattern { get; set; }
          /// <summary>
          /// 查找程序集列表
          /// </summary>
          List<Assembly> Find();
      }
      
      /// <summary>
      /// 應(yīng)用程序域程序集查找器
      /// </summary>
      public class AppDomainAssemblyFinder : IAssemblyFinder {
          /// <summary>
          /// 程序集過濾模式
          /// </summary>
          public string AssemblySkipPattern { get; set; }
          /// <summary>
          /// 程序集列表
          /// </summary>
          private List<Assembly> _assemblies;
      
          /// <summary>
          /// 獲取程序集列表
          /// </summary>
          public List<Assembly> Find() {
              if ( _assemblies != null )
                  return _assemblies;
              _assemblies = new List<Assembly>();
              LoadAssemblies();
              foreach( var assembly in AppDomain.CurrentDomain.GetAssemblies() ) {
                  if( IsSkip( assembly ) )
                      continue;
                  _assemblies.Add( assembly );
              }
              return _assemblies;
          }
      
          /// <summary>
          /// 加載引用但尚未調(diào)用的程序集列表到當(dāng)前應(yīng)用程序域
          /// </summary>
          protected virtual void LoadAssemblies() {
              var currentDomainAssemblies = AppDomain.CurrentDomain.GetAssemblies();
              foreach( string file in GetLoadAssemblyFiles() )
                  LoadAssembly( file, currentDomainAssemblies );
          }
      
          /// <summary>
          /// 獲取需要加載的程序集文件列表
          /// </summary>
          protected virtual string[] GetLoadAssemblyFiles() {
              return Directory.GetFiles( AppContext.BaseDirectory, "*.dll" );
          }
      
          /// <summary>
          /// 加載程序集到當(dāng)前應(yīng)用程序域
          /// </summary>
          protected void LoadAssembly( string file, Assembly[] currentDomainAssemblies ) {
              try {
                  var assemblyName = AssemblyName.GetAssemblyName( file );
                  if( IsSkip( assemblyName.Name ) )
                      return;
                  if( currentDomainAssemblies.Any( t => t.FullName == assemblyName.FullName ) )
                      return;
                  AppDomain.CurrentDomain.Load( assemblyName );
              }
              catch( BadImageFormatException ) {
              }
          }
      
          /// <summary>
          /// 是否過濾程序集
          /// </summary>
          protected bool IsSkip( string assemblyName ) {
              var applicationName = Assembly.GetEntryAssembly()?.GetName().Name;
              if ( assemblyName.StartsWith( $"{applicationName}.Views" ) )
                  return true;
              if( assemblyName.StartsWith( $"{applicationName}.PrecompiledViews" ) )
                  return true;
              if ( string.IsNullOrWhiteSpace( AssemblySkipPattern ) )
                  return false;
              return Regex.IsMatch( assemblyName, AssemblySkipPattern, RegexOptions.IgnoreCase | RegexOptions.Compiled );
          }
      
          /// <summary>
          /// 是否過濾程序集
          /// </summary>
          private bool IsSkip( Assembly assembly ) {
              return IsSkip( assembly.FullName );
          }
      }
      

      配置程序集過濾列表

      Util應(yīng)用框架已經(jīng)排除了引用的所有依賴庫程序集.

      但你的項(xiàng)目可能引用其它第三方類庫,如果只引用了少量類庫,影響非常小,但引用大量類庫,則必須配置程序集過濾列表.

      如果你不想在每個(gè)項(xiàng)目配置程序集過濾,可以讓Util應(yīng)用框架更新過濾列表,請把要過濾的程序集名稱告訴我們.

      Util.Infrastructure.BootstrapperConfig 是啟動(dòng)器配置, AssemblySkipPattern 屬性提供了程序集過濾列表.

      程序集過濾列表是一個(gè)正則表達(dá)式,使用 | 分隔程序集,使用 ^ 匹配起始名稱過濾.

      范例1

      如果你想排除名為 Demo 的程序集.

      BootstrapperConfig.AssemblySkipPattern += "|Demo";
      
      builder.AsBuild().AddUtil();
      

      必須在 AddUtil 之前設(shè)置 BootstrapperConfig.AssemblySkipPattern 屬性.

      范例2

      排除 Demo 開頭的程序集,比如 Demo.A,Demo.B .

      BootstrapperConfig.AssemblySkipPattern += "|^Demo";
      
      posted @ 2023-10-30 11:43  何鎮(zhèn)汐  閱讀(576)  評(píng)論(0)    收藏  舉報(bào)
      主站蜘蛛池模板: 无码人妻精品一区二区三区蜜桃| 强开少妇嫩苞又嫩又紧九色| 人人人澡人人肉久久精品| 中国女人高潮hd| 一区二区三区午夜无码视频| 一二三四日本高清社区5| 亚洲国产综合性亚洲综合性| 四虎成人精品国产永久免费| 男人av无码天堂| 国产欧美日韩高清在线不卡| 国产熟女精品一区二区三区| 亚洲欧美在线一区中文字幕| 中文字幕人妻av第一区| 果冻传媒色av国产在线播放| 在线精品国产中文字幕| 久久精品免视看国产成人| 国产99久久无码精品| av午夜福利一片免费看久久| 人妻精品久久无码区| 麻豆精产国品一二三产 | 94人妻少妇偷人精品| 国产白嫩护士被弄高潮| 国产精自产拍久久久久久蜜| 亚洲国产无套无码av电影| 亚洲AV成人无码精品电影在线| 国产第一页浮力影院入口| 国产老肥熟一区二区三区| 中文字幕在线国产精品| 亚洲狠狠婷婷综合久久久| 啊灬啊灬啊灬快灬高潮了电影片段| 日本黄色一区二区三区四区| 四房播色综合久久婷婷| 亚洲av激情五月性综合| 色噜噜亚洲男人的天堂| 狠狠色噜噜狠狠狠狠蜜桃 | 蜜臀av性久久久久蜜臀aⅴ麻豆 | 昭觉县| 天干天干夜啦天干天干国产| 一区二区三区国产综合在线| 无码一区二区三区久久精品| 吉川爱美一区二区三区视频|