@@ -17,6 +17,10 @@ namespace Senparc.CO2NET.WebApi.WebApiEngines
1717 /// </summary>
1818 public static class WebApiEngineExtensions
1919 {
20+ public static object WebApiInitObject = new object ( ) ;
21+ public static bool WebApiInitFinished = false ;
22+
23+
2024 /// <summary>
2125 /// 初始化动态API
2226 /// </summary>
@@ -49,107 +53,128 @@ public static void AddAndInitDynamicApi(this IServiceCollection services, IMvcBu
4953 /// <param name="builder"></param>
5054 /// <param name="services"></param>
5155 /// <param name="options"> WebApiEngine 配置</param>
52- private static void AddAndInitDynamicApi ( this IServiceCollection services ,
53- ( IMvcCoreBuilder coreBuilder , IMvcBuilder builder ) builder ,
56+ private static void AddAndInitDynamicApi ( this IServiceCollection services ,
57+ ( IMvcCoreBuilder coreBuilder , IMvcBuilder builder ) builder ,
5458 Action < WebApiEngineOptions > options = null )
5559 {
56- services . AddScoped < FindApiService > ( ) ;
57- services . AddScoped ( s => new WebApiEngine ( options ) ) ;
58-
59- var webApiEngine = new WebApiEngine ( options ) ;
60-
61- bool preLoad = true ;
62-
63- //确保 ApiBind 已经执行扫描和注册过程
64- services . AddApiBind ( preLoad ) ; //参数为 true,确保重试绑定成功
65-
66- //确保目录存在
67- if ( webApiEngine . BuildXml )
60+ lock ( WebApiInitObject )
6861 {
69- webApiEngine . TryCreateDir ( webApiEngine . DocXmlPath ) ;
70- }
62+ if ( WebApiInitFinished )
63+ {
64+ return ;
65+ }
66+
67+ try
68+ {
7169
72- var dt1 = SystemTime . Now ;
70+ services . AddScoped < FindApiService > ( ) ;
71+ services . AddScoped ( s => new WebApiEngine ( options ) ) ;
7372
74- var apiGroups = ApiBindInfoCollection . Instance . GetGroupedCollection ( ) ;
75- var apiGouupsCount = apiGroups . Count ( ) ;
73+ var webApiEngine = new WebApiEngine ( options ) ;
7674
77- ConcurrentDictionary < string , ( int apiCount , double costMs ) > assemblyBuildStat = new ConcurrentDictionary < string , ( int , double ) > ( ) ;
75+ bool preLoad = true ;
7876
79- List < Task > taskList = new List < Task > ( ) ;
77+ //确保 ApiBind 已经执行扫描和注册过程
78+ services . AddApiBind ( preLoad ) ; //参数为 true,确保重试绑定成功
8079
81- //因为模块数量比较少,这里使用异步反而会开销略大
82- //WeixinApiAssemblyNames.Keys.AsParallel().ForAll(async category =>
83- //WeixinApiAssemblyNames.Keys.ToList().ForEach(category =>
84- var keys = WebApiEngine . ApiAssemblyNames . Keys . ToList ( ) ;
85- for ( int i = 0 ; i < keys . Count ; i ++ )
86- {
87- var category = keys [ i ] ;
88- var threadIndex = i ;
89- var wrapperTask = Task . Factory . StartNew ( async ( ) =>
90- {
91- try
80+ //确保目录存在
81+ if ( webApiEngine . BuildXml )
9282 {
83+ webApiEngine . TryCreateDir ( webApiEngine . DocXmlPath ) ;
84+ }
9385
94- //此处使用 Task 效率并不比 Keys.ToList() 方法快
95- webApiEngine . WriteLog ( $ "Get API Groups: { threadIndex + 1 } /{ apiGouupsCount } , now dealing with: { category } ") ;
96- var dtStart = SystemTime . Now ;
97- var apiBindGroup = apiGroups . FirstOrDefault ( z => z . Key == category ) ;
86+ var dt1 = SystemTime . Now ;
9887
99- var apiCount = await webApiEngine . BuildWebApi ( apiBindGroup ) . ConfigureAwait ( false ) ;
100- var apiAssembly = webApiEngine . GetApiAssembly ( category ) ;
88+ var apiGroups = ApiBindInfoCollection . Instance . GetGroupedCollection ( ) ;
89+ var apiGouupsCount = apiGroups . Count ( ) ;
10190
102- //程序部件:https://docs.microsoft.com/zh-cn/aspnet/core/mvc/advanced/app-parts?view=aspnetcore-2.2
103- if ( builder . coreBuilder != null )
104- {
105- builder . coreBuilder . AddApplicationPart ( apiAssembly ) ;
106- }
107- else
108- {
109- builder . builder . AddApplicationPart ( apiAssembly ) ;
110- }
91+ ConcurrentDictionary < string , ( int apiCount , double costMs ) > assemblyBuildStat = new ConcurrentDictionary < string , ( int , double ) > ( ) ;
11192
112- assemblyBuildStat [ category ] = ( apiCount : apiCount , costMs : SystemTime . DiffTotalMS ( dtStart ) ) ;
113- }
114- catch ( Exception ex )
93+ List < Task > taskList = new List < Task > ( ) ;
94+
95+ //因为模块数量比较少,这里使用异步反而会开销略大
96+ //WeixinApiAssemblyNames.Keys.AsParallel().ForAll(async category =>
97+ //WeixinApiAssemblyNames.Keys.ToList().ForEach(category =>
98+ var keys = WebApiEngine . ApiAssemblyNames . Keys . ToList ( ) ;
99+ for ( int i = 0 ; i < keys . Count ; i ++ )
115100 {
116- SenparcTrace . BaseExceptionLog ( ex ) ;
101+ var category = keys [ i ] ;
102+ var threadIndex = i ;
103+ var wrapperTask = Task . Factory . StartNew ( async ( ) =>
104+ {
105+ try
106+ {
107+
108+ //此处使用 Task 效率并不比 Keys.ToList() 方法快
109+ webApiEngine . WriteLog ( $ "Get API Groups: { threadIndex + 1 } /{ apiGouupsCount } , now dealing with: { category } ") ;
110+ var dtStart = SystemTime . Now ;
111+ var apiBindGroup = apiGroups . FirstOrDefault ( z => z . Key == category ) ;
112+
113+ var apiCount = await webApiEngine . BuildWebApi ( apiBindGroup ) . ConfigureAwait ( false ) ;
114+ var apiAssembly = webApiEngine . GetApiAssembly ( category ) ;
115+
116+ //程序部件:https://docs.microsoft.com/zh-cn/aspnet/core/mvc/advanced/app-parts?view=aspnetcore-2.2
117+ if ( builder . coreBuilder != null )
118+ {
119+ builder . coreBuilder . AddApplicationPart ( apiAssembly ) ;
120+ }
121+ else
122+ {
123+ builder . builder . AddApplicationPart ( apiAssembly ) ;
124+ }
125+
126+ assemblyBuildStat [ category ] = ( apiCount : apiCount , costMs : SystemTime . DiffTotalMS ( dtStart ) ) ;
127+ }
128+ catch ( Exception ex )
129+ {
130+ SenparcTrace . BaseExceptionLog ( ex ) ;
131+ }
132+ } ) ;
133+ taskList . Add ( wrapperTask . Unwrap ( ) ) ;
117134 }
118- } ) ;
119- taskList . Add ( wrapperTask . Unwrap ( ) ) ;
120- }
121- //foreach (var category in WebApiEngine.ApiAssemblyNames.Keys)
122- //{
135+ //foreach (var category in WebApiEngine.ApiAssemblyNames.Keys)
136+ //{
123137
124- //}
138+ //}
125139
126- Task . WaitAll ( taskList . ToArray ( ) ) ;
140+ Task . WaitAll ( taskList . ToArray ( ) ) ;
127141
128- //保存 XML文件
129- webApiEngine . SaveDynamicApiXml ( ) ;
142+ //保存 XML文件
143+ webApiEngine . SaveDynamicApiXml ( ) ;
130144
131- #region 统计数据
132- var totalCost = SystemTime . DiffTotalMS ( dt1 ) ;
145+ #region 统计数据
146+ var totalCost = SystemTime . DiffTotalMS ( dt1 ) ;
133147
134- //Func<object, int, string> outputResult = (text, length) => string.Format($"{{0,{length}}}", text);
148+ //Func<object, int, string> outputResult = (text, length) => string.Format($"{{0,{length}}}", text);
135149
136- webApiEngine . WriteLog ( "" ) ;
137- webApiEngine . WriteLog ( string . Format ( "{0,35} | {1,15}| {2,15} |{3,15}" , "Category Name" , "API Count" , "Cost Time" , "Average" ) ) ;
138- webApiEngine . WriteLog ( new string ( '-' , 90 ) ) ;
139- foreach ( var item in assemblyBuildStat )
140- {
141- var apiCount = item . Value . apiCount ;
142- var cost = item . Value . costMs ;
143- var avg = Math . Round ( cost / apiCount , 3 ) ;
144- webApiEngine . WriteLog ( string . Format ( "{0,35} | {1,15}| {2,15} |{3,15}" , item . Key , apiCount , $ "{ cost } ms", $ "{ avg } ms") ) ;
150+ webApiEngine . WriteLog ( "" ) ;
151+ webApiEngine . WriteLog ( string . Format ( "{0,35} | {1,15}| {2,15} |{3,15}" , "Category Name" , "API Count" , "Cost Time" , "Average" ) ) ;
152+ webApiEngine . WriteLog ( new string ( '-' , 90 ) ) ;
153+ foreach ( var item in assemblyBuildStat )
154+ {
155+ var apiCount = item . Value . apiCount ;
156+ var cost = item . Value . costMs ;
157+ var avg = Math . Round ( cost / apiCount , 3 ) ;
158+ webApiEngine . WriteLog ( string . Format ( "{0,35} | {1,15}| {2,15} |{3,15}" , item . Key , apiCount , $ "{ cost } ms", $ "{ avg } ms") ) ;
159+ }
160+ webApiEngine . WriteLog ( new string ( '=' , 90 ) ) ;
161+ var totalApi = assemblyBuildStat . Values . Sum ( z => z . apiCount ) ;
162+ webApiEngine . WriteLog ( string . Format ( "{0,35} | {1,15}| {2,15} |{3,15}" , $ "Total", $ "API Count:{ totalApi } ", $ "Cost:{ totalCost } ms", $ "" ) ) ;
163+ webApiEngine . WriteLog ( $ "Total Average Cost: { Math . Round ( totalCost / totalApi , 4 ) } ms \t \t Task Count: { webApiEngine . TaskCount } ") ;
164+ webApiEngine . WriteLog ( "" ) ;
165+
166+ #endregion
167+ }
168+ catch ( Exception ex )
169+ {
170+ SenparcTrace . BaseExceptionLog ( ex ) ;
171+ }
172+ finally
173+ {
174+ WebApiInitFinished = true ;
175+ }
145176 }
146- webApiEngine . WriteLog ( new string ( '=' , 90 ) ) ;
147- var totalApi = assemblyBuildStat . Values . Sum ( z => z . apiCount ) ;
148- webApiEngine . WriteLog ( string . Format ( "{0,35} | {1,15}| {2,15} |{3,15}" , $ "Total", $ "API Count:{ totalApi } ", $ "Cost:{ totalCost } ms", $ "" ) ) ;
149- webApiEngine . WriteLog ( $ "Total Average Cost: { Math . Round ( totalCost / totalApi , 4 ) } ms \t \t Task Count: { webApiEngine . TaskCount } ") ;
150- webApiEngine . WriteLog ( "" ) ;
151177
152- #endregion
153178 }
154179
155180
0 commit comments