Ioc.cs 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651
  1. using Microsoft.Extensions.DependencyInjection;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. namespace Vit.Ioc
  6. {
  7. public class Ioc
  8. {
  9. #region AddTransient
  10. /// <summary>
  11. /// Adds a transient service of the type specified in <paramref name="serviceType" /> with an
  12. /// implementation of the type specified in <paramref name="implementationType" /> to the
  13. /// specified <see cref="T:Microsoft.Extensions.DependencyInjection.IServiceCollection" />.
  14. /// </summary>
  15. /// <param name="serviceType">The type of the service to register.</param>
  16. /// <param name="implementationType">The implementation type of the service.</param>
  17. /// <returns>A reference to this instance after the operation has completed.</returns>
  18. /// <seealso cref="F:Microsoft.Extensions.DependencyInjection.ServiceLifetime.Transient" />
  19. public void AddTransient(Type serviceType, Type implementationType)
  20. {
  21. rootServiceCollection.AddTransient(serviceType, implementationType);
  22. }
  23. /// <summary>
  24. /// Adds a transient service of the type specified in <paramref name="serviceType" /> with a
  25. /// factory specified in <paramref name="implementationFactory" /> to the
  26. /// specified <see cref="T:Microsoft.Extensions.DependencyInjection.IServiceCollection" />.
  27. /// </summary>
  28. /// <param name="serviceType">The type of the service to register.</param>
  29. /// <param name="implementationFactory">The factory that creates the service.</param>
  30. /// <returns>A reference to this instance after the operation has completed.</returns>
  31. /// <seealso cref="F:Microsoft.Extensions.DependencyInjection.ServiceLifetime.Transient" />
  32. public void AddTransient(Type serviceType, Func<IServiceProvider, object> implementationFactory)
  33. {
  34. rootServiceCollection.AddTransient(serviceType, implementationFactory);
  35. }
  36. /// <summary>
  37. /// Adds a transient service of the type specified in <typeparamref name="TService" /> with an
  38. /// implementation type specified in <typeparamref name="TImplementation" /> to the
  39. /// specified <see cref="T:Microsoft.Extensions.DependencyInjection.IServiceCollection" />.
  40. /// </summary>
  41. /// <typeparam name="TService">The type of the service to add.</typeparam>
  42. /// <typeparam name="TImplementation">The type of the implementation to use.</typeparam>
  43. /// <returns>A reference to this instance after the operation has completed.</returns>
  44. /// <seealso cref="F:Microsoft.Extensions.DependencyInjection.ServiceLifetime.Transient" />
  45. public void AddTransient<TService, TImplementation>() where TService : class where TImplementation : class, TService
  46. {
  47. rootServiceCollection.AddTransient<TService, TImplementation>();
  48. }
  49. /// <summary>
  50. /// Adds a transient service of the type specified in <paramref name="serviceType" /> to the
  51. /// specified <see cref="T:Microsoft.Extensions.DependencyInjection.IServiceCollection" />.
  52. /// </summary>
  53. /// <param name="serviceType">The type of the service to register and the implementation to use.</param>
  54. /// <returns>A reference to this instance after the operation has completed.</returns>
  55. /// <seealso cref="F:Microsoft.Extensions.DependencyInjection.ServiceLifetime.Transient" />
  56. public void AddTransient(Type serviceType)
  57. {
  58. rootServiceCollection.AddTransient(serviceType);
  59. }
  60. /// <summary>
  61. /// Adds a transient service of the type specified in <typeparamref name="TService" /> to the
  62. /// specified <see cref="T:Microsoft.Extensions.DependencyInjection.IServiceCollection" />.
  63. /// </summary>
  64. /// <typeparam name="TService">The type of the service to add.</typeparam>
  65. /// <returns>A reference to this instance after the operation has completed.</returns>
  66. /// <seealso cref="F:Microsoft.Extensions.DependencyInjection.ServiceLifetime.Transient" />
  67. public void AddTransient<TService>() where TService : class
  68. {
  69. rootServiceCollection.AddTransient<TService>();
  70. }
  71. /// <summary>
  72. /// Adds a transient service of the type specified in <typeparamref name="TService" /> with a
  73. /// factory specified in <paramref name="implementationFactory" /> to the
  74. /// specified <see cref="T:Microsoft.Extensions.DependencyInjection.IServiceCollection" />.
  75. /// </summary>
  76. /// <typeparam name="TService">The type of the service to add.</typeparam>
  77. /// <param name="implementationFactory">The factory that creates the service.</param>
  78. /// <returns>A reference to this instance after the operation has completed.</returns>
  79. /// <seealso cref="F:Microsoft.Extensions.DependencyInjection.ServiceLifetime.Transient" />
  80. public void AddTransient<TService>(Func<IServiceProvider, TService> implementationFactory) where TService : class
  81. {
  82. rootServiceCollection.AddTransient<TService>(implementationFactory);
  83. }
  84. /// <summary>
  85. /// Adds a transient service of the type specified in <typeparamref name="TService" /> with an
  86. /// implementation type specified in <typeparamref name="TImplementation" /> using the
  87. /// factory specified in <paramref name="implementationFactory" /> to the
  88. /// specified <see cref="T:Microsoft.Extensions.DependencyInjection.IServiceCollection" />.
  89. /// </summary>
  90. /// <typeparam name="TService">The type of the service to add.</typeparam>
  91. /// <typeparam name="TImplementation">The type of the implementation to use.</typeparam>
  92. /// <param name="implementationFactory">The factory that creates the service.</param>
  93. /// <returns>A reference to this instance after the operation has completed.</returns>
  94. /// <seealso cref="F:Microsoft.Extensions.DependencyInjection.ServiceLifetime.Transient" />
  95. public void AddTransient<TService, TImplementation>(Func<IServiceProvider, TImplementation> implementationFactory) where TService : class where TImplementation : class, TService
  96. {
  97. rootServiceCollection.AddTransient<TService, TImplementation>(implementationFactory);
  98. }
  99. #endregion
  100. #region AddScoped
  101. /// <summary>
  102. /// Adds a scoped service of the type specified in <paramref name="serviceType" /> with an
  103. /// implementation of the type specified in <paramref name="implementationType" /> to the
  104. /// specified <see cref="T:Microsoft.Extensions.DependencyInjection.IServiceCollection" />.
  105. /// </summary>
  106. /// <param name="serviceType">The type of the service to register.</param>
  107. /// <param name="implementationType">The implementation type of the service.</param>
  108. /// <returns>A reference to this instance after the operation has completed.</returns>
  109. /// <seealso cref="F:Microsoft.Extensions.DependencyInjection.ServiceLifetime.Scoped" />
  110. public void AddScoped(Type serviceType, Type implementationType)
  111. {
  112. rootServiceCollection.AddScoped(serviceType, implementationType);
  113. }
  114. /// <summary>
  115. /// Adds a scoped service of the type specified in <paramref name="serviceType" /> with a
  116. /// factory specified in <paramref name="implementationFactory" /> to the
  117. /// specified <see cref="T:Microsoft.Extensions.DependencyInjection.IServiceCollection" />.
  118. /// </summary>
  119. /// <param name="serviceType">The type of the service to register.</param>
  120. /// <param name="implementationFactory">The factory that creates the service.</param>
  121. /// <returns>A reference to this instance after the operation has completed.</returns>
  122. /// <seealso cref="F:Microsoft.Extensions.DependencyInjection.ServiceLifetime.Scoped" />
  123. public void AddScoped(Type serviceType, Func<IServiceProvider, object> implementationFactory)
  124. {
  125. rootServiceCollection.AddScoped(serviceType, implementationFactory);
  126. }
  127. /// <summary>
  128. /// Adds a scoped service of the type specified in <typeparamref name="TService" /> with an
  129. /// implementation type specified in <typeparamref name="TImplementation" /> to the
  130. /// specified <see cref="T:Microsoft.Extensions.DependencyInjection.IServiceCollection" />.
  131. /// </summary>
  132. /// <typeparam name="TService">The type of the service to add.</typeparam>
  133. /// <typeparam name="TImplementation">The type of the implementation to use.</typeparam>
  134. /// <returns>A reference to this instance after the operation has completed.</returns>
  135. /// <seealso cref="F:Microsoft.Extensions.DependencyInjection.ServiceLifetime.Scoped" />
  136. public void AddScoped<TService, TImplementation>() where TService : class where TImplementation : class, TService
  137. {
  138. rootServiceCollection.AddScoped<TService, TImplementation>();
  139. }
  140. /// <summary>
  141. /// Adds a scoped service of the type specified in <paramref name="serviceType" /> to the
  142. /// specified <see cref="T:Microsoft.Extensions.DependencyInjection.IServiceCollection" />.
  143. /// </summary>
  144. /// <param name="serviceType">The type of the service to register and the implementation to use.</param>
  145. /// <returns>A reference to this instance after the operation has completed.</returns>
  146. /// <seealso cref="F:Microsoft.Extensions.DependencyInjection.ServiceLifetime.Scoped" />
  147. public void AddScoped(Type serviceType)
  148. {
  149. rootServiceCollection.AddScoped(serviceType);
  150. }
  151. /// <summary>
  152. /// Adds a scoped service of the type specified in <typeparamref name="TService" /> to the
  153. /// specified <see cref="T:Microsoft.Extensions.DependencyInjection.IServiceCollection" />.
  154. /// </summary>
  155. /// <typeparam name="TService">The type of the service to add.</typeparam>
  156. /// <returns>A reference to this instance after the operation has completed.</returns>
  157. /// <seealso cref="F:Microsoft.Extensions.DependencyInjection.ServiceLifetime.Scoped" />
  158. public void AddScoped<TService>() where TService : class
  159. {
  160. rootServiceCollection.AddScoped<TService>();
  161. }
  162. /// <summary>
  163. /// Adds a scoped service of the type specified in <typeparamref name="TService" /> with a
  164. /// factory specified in <paramref name="implementationFactory" /> to the
  165. /// specified <see cref="T:Microsoft.Extensions.DependencyInjection.IServiceCollection" />.
  166. /// </summary>
  167. /// <typeparam name="TService">The type of the service to add.</typeparam>
  168. /// <param name="implementationFactory">The factory that creates the service.</param>
  169. /// <returns>A reference to this instance after the operation has completed.</returns>
  170. /// <seealso cref="F:Microsoft.Extensions.DependencyInjection.ServiceLifetime.Scoped" />
  171. public void AddScoped<TService>(Func<IServiceProvider, TService> implementationFactory) where TService : class
  172. {
  173. rootServiceCollection.AddScoped<TService>(implementationFactory);
  174. }
  175. /// <summary>
  176. /// Adds a scoped service of the type specified in <typeparamref name="TService" /> with an
  177. /// implementation type specified in <typeparamref name="TImplementation" /> using the
  178. /// factory specified in <paramref name="implementationFactory" /> to the
  179. /// specified <see cref="T:Microsoft.Extensions.DependencyInjection.IServiceCollection" />.
  180. /// </summary>
  181. /// <typeparam name="TService">The type of the service to add.</typeparam>
  182. /// <typeparam name="TImplementation">The type of the implementation to use.</typeparam>
  183. /// <param name="implementationFactory">The factory that creates the service.</param>
  184. /// <returns>A reference to this instance after the operation has completed.</returns>
  185. /// <seealso cref="F:Microsoft.Extensions.DependencyInjection.ServiceLifetime.Scoped" />
  186. public void AddScoped<TService, TImplementation>(Func<IServiceProvider, TImplementation> implementationFactory) where TService : class where TImplementation : class, TService
  187. {
  188. rootServiceCollection.AddScoped<TService, TImplementation>(implementationFactory);
  189. }
  190. #endregion
  191. #region AddSingleton
  192. /// <summary>
  193. /// Adds a singleton service of the type specified in <paramref name="serviceType" /> with an
  194. /// implementation of the type specified in <paramref name="implementationType" /> to the
  195. /// specified <see cref="T:Microsoft.Extensions.DependencyInjection.IServiceCollection" />.
  196. /// </summary>
  197. /// <param name="serviceType">The type of the service to register.</param>
  198. /// <param name="implementationType">The implementation type of the service.</param>
  199. /// <returns>A reference to this instance after the operation has completed.</returns>
  200. /// <seealso cref="F:Microsoft.Extensions.DependencyInjection.ServiceLifetime.Singleton" />
  201. public void AddSingleton(Type serviceType, Type implementationType)
  202. {
  203. rootServiceCollection.AddSingleton(serviceType, implementationType);
  204. }
  205. /// <summary>
  206. /// Adds a singleton service of the type specified in <paramref name="serviceType" /> with a
  207. /// factory specified in <paramref name="implementationFactory" /> to the
  208. /// specified <see cref="T:Microsoft.Extensions.DependencyInjection.IServiceCollection" />.
  209. /// </summary>
  210. /// <param name="serviceType">The type of the service to register.</param>
  211. /// <param name="implementationFactory">The factory that creates the service.</param>
  212. /// <returns>A reference to this instance after the operation has completed.</returns>
  213. /// <seealso cref="F:Microsoft.Extensions.DependencyInjection.ServiceLifetime.Singleton" />
  214. public void AddSingleton(Type serviceType, Func<IServiceProvider, object> implementationFactory)
  215. {
  216. rootServiceCollection.AddSingleton(serviceType, implementationFactory);
  217. }
  218. /// <summary>
  219. /// Adds a singleton service of the type specified in <typeparamref name="TService" /> with an
  220. /// implementation type specified in <typeparamref name="TImplementation" /> to the
  221. /// specified <see cref="T:Microsoft.Extensions.DependencyInjection.IServiceCollection" />.
  222. /// </summary>
  223. /// <typeparam name="TService">The type of the service to add.</typeparam>
  224. /// <typeparam name="TImplementation">The type of the implementation to use.</typeparam>
  225. /// <returns>A reference to this instance after the operation has completed.</returns>
  226. /// <seealso cref="F:Microsoft.Extensions.DependencyInjection.ServiceLifetime.Singleton" />
  227. public void AddSingleton<TService, TImplementation>()
  228. where TService : class
  229. where TImplementation : class, TService
  230. {
  231. rootServiceCollection.AddSingleton<TService, TImplementation>();
  232. }
  233. /// <summary>
  234. /// Adds a singleton service of the type specified in <paramref name="serviceType" /> to the
  235. /// specified <see cref="T:Microsoft.Extensions.DependencyInjection.IServiceCollection" />.
  236. /// </summary>
  237. /// <param name="serviceType">The type of the service to register and the implementation to use.</param>
  238. /// <returns>A reference to this instance after the operation has completed.</returns>
  239. /// <seealso cref="F:Microsoft.Extensions.DependencyInjection.ServiceLifetime.Singleton" />
  240. public void AddSingleton(Type serviceType)
  241. {
  242. rootServiceCollection.AddSingleton(serviceType);
  243. }
  244. /// <summary>
  245. /// Adds a singleton service of the type specified in <typeparamref name="TService" /> to the
  246. /// specified <see cref="T:Microsoft.Extensions.DependencyInjection.IServiceCollection" />.
  247. /// </summary>
  248. /// <typeparam name="TService">The type of the service to add.</typeparam>
  249. /// <returns>A reference to this instance after the operation has completed.</returns>
  250. /// <seealso cref="F:Microsoft.Extensions.DependencyInjection.ServiceLifetime.Singleton" />
  251. public void AddSingleton<TService>()
  252. where TService : class
  253. {
  254. rootServiceCollection.AddSingleton<TService>();
  255. }
  256. /// <summary>
  257. /// Adds a singleton service of the type specified in <typeparamref name="TService" /> with a
  258. /// factory specified in <paramref name="implementationFactory" /> to the
  259. /// specified <see cref="T:Microsoft.Extensions.DependencyInjection.IServiceCollection" />.
  260. /// </summary>
  261. /// <typeparam name="TService">The type of the service to add.</typeparam>
  262. /// <param name="implementationFactory">The factory that creates the service.</param>
  263. /// <returns>A reference to this instance after the operation has completed.</returns>
  264. /// <seealso cref="F:Microsoft.Extensions.DependencyInjection.ServiceLifetime.Singleton" />
  265. public void AddSingleton<TService>(Func<IServiceProvider, TService> implementationFactory) where TService : class
  266. {
  267. rootServiceCollection.AddSingleton<TService>(implementationFactory);
  268. }
  269. /// <summary>
  270. /// Adds a singleton service of the type specified in <typeparamref name="TService" /> with an
  271. /// implementation type specified in <typeparamref name="TImplementation" /> using the
  272. /// factory specified in <paramref name="implementationFactory" /> to the
  273. /// specified <see cref="T:Microsoft.Extensions.DependencyInjection.IServiceCollection" />.
  274. /// </summary>
  275. /// <typeparam name="TService">The type of the service to add.</typeparam>
  276. /// <typeparam name="TImplementation">The type of the implementation to use.</typeparam>
  277. /// <param name="implementationFactory">The factory that creates the service.</param>
  278. /// <returns>A reference to this instance after the operation has completed.</returns>
  279. /// <seealso cref="F:Microsoft.Extensions.DependencyInjection.ServiceLifetime.Singleton" />
  280. public void AddSingleton<TService, TImplementation>(Func<IServiceProvider, TImplementation> implementationFactory) where TService : class where TImplementation : class, TService
  281. {
  282. rootServiceCollection.AddSingleton<TService, TImplementation>(implementationFactory);
  283. }
  284. /// <summary>
  285. /// Adds a singleton service of the type specified in <paramref name="serviceType" /> with an
  286. /// instance specified in <paramref name="implementationInstance" /> to the
  287. /// specified <see cref="T:Microsoft.Extensions.DependencyInjection.IServiceCollection" />.
  288. /// </summary>
  289. /// <param name="serviceType">The type of the service to register.</param>
  290. /// <param name="implementationInstance">The instance of the service.</param>
  291. /// <returns>A reference to this instance after the operation has completed.</returns>
  292. /// <seealso cref="F:Microsoft.Extensions.DependencyInjection.ServiceLifetime.Singleton" />
  293. public void AddSingleton(Type serviceType, object implementationInstance)
  294. {
  295. rootServiceCollection.AddSingleton(serviceType, implementationInstance);
  296. }
  297. /// <summary>
  298. /// Adds a singleton service of the type specified in <typeparamref name="TService" /> with an
  299. /// instance specified in <paramref name="implementationInstance" /> to the
  300. /// specified <see cref="T:Microsoft.Extensions.DependencyInjection.IServiceCollection" />.
  301. /// </summary>
  302. /// <param name="implementationInstance">The instance of the service.</param>
  303. /// <returns>A reference to this instance after the operation has completed.</returns>
  304. /// <seealso cref="F:Microsoft.Extensions.DependencyInjection.ServiceLifetime.Singleton" />
  305. public void AddSingleton<TService>(TService implementationInstance) where TService : class
  306. {
  307. rootServiceCollection.AddSingleton<TService>(implementationInstance);
  308. }
  309. #endregion
  310. #region Create
  311. /// <summary>
  312. /// Get service of type <typeparamref name="T" /> from the <see cref="T:System.IServiceProvider" />.
  313. /// </summary>
  314. /// <typeparam name="T">The type of service object to get.</typeparam>
  315. /// <returns>A service object of type <typeparamref name="T" /> or null if there is no such service.</returns>
  316. public T Create<T>()
  317. {
  318. //lock (this)
  319. //{
  320. return CurServiceProvider.GetService<T>();
  321. //}
  322. }
  323. /// <summary>Gets the service object of the specified type.</summary>
  324. /// <param name="serviceType">An object that specifies the type of service object to get.</param>
  325. /// <returns>A service object of type <paramref name="serviceType">serviceType</paramref>.
  326. /// -or-
  327. /// null if there is no service object of type <paramref name="serviceType">serviceType</paramref>.</returns>
  328. public object Create (Type serviceType)
  329. {
  330. //lock (this)
  331. //{
  332. return CurServiceProvider.GetService(serviceType);
  333. //}
  334. }
  335. #endregion
  336. #region AutoCreate
  337. /// <summary>
  338. /// Get service of type <typeparamref name="T" /> from the <see cref="T:System.IServiceProvider" />.
  339. /// if have not yet registered Type T in Ioc,then return new T();
  340. /// </summary>
  341. /// <typeparam name="T">The type of service object to get.</typeparam>
  342. /// <returns>A service object of type <typeparamref name="T" /> or null if there is no such service.</returns>
  343. public T AutoCreate<T>()where T: class,new()
  344. {
  345. //lock (this)
  346. //{
  347. return Create<T>() ?? new T();
  348. //}
  349. }
  350. /// <summary>
  351. /// Get service of type <typeparamref name="TService" /> from the <see cref="TService:System.IServiceProvider" />.
  352. /// if have not yet registered Type TService in Ioc,then return new TImplementation();
  353. /// </summary>
  354. /// <typeparam name="TService">The type of the service to add.</typeparam>
  355. /// <typeparam name="TImplementation">The type of the implementation to use.</typeparam>
  356. /// <returns>A reference to this instance after the operation has completed.</returns>
  357. /// <seealso cref="F:Microsoft.Extensions.DependencyInjection.ServiceLifetime.Transient" />
  358. public TService AutoCreate<TService, TImplementation>()
  359. where TService : class
  360. where TImplementation : class, TService, new()
  361. {
  362. //lock (this)
  363. //{
  364. return Create<TService>() ?? new TImplementation();
  365. //}
  366. }
  367. #endregion
  368. #region 逻辑
  369. #region 成员变量
  370. #region AsyncCache
  371. #region class AsyncCache<T>
  372. /// <summary>
  373. /// 多包裹一层的原因是 子异步任务结束时会还原子异步任务对AsyncLocal做的更改(即子异步任务对AsyncLocal做的更改不会保留到子异步任务结束后的父异步任务中)
  374. /// 参见https://blog.csdn.net/kkfd1002/article/details/80102244
  375. /// </summary>
  376. class AsyncCache<T>
  377. {
  378. readonly System.Threading.AsyncLocal<CachedData> _AsyncLocal = new System.Threading.AsyncLocal<CachedData>();
  379. class CachedData
  380. {
  381. public T Cache;
  382. }
  383. public T Value
  384. {
  385. get
  386. {
  387. if (null == _AsyncLocal.Value)
  388. return default(T);
  389. return _AsyncLocal.Value.Cache;
  390. }
  391. set
  392. {
  393. var asyncLocal = _AsyncLocal.Value;
  394. if (null == asyncLocal) asyncLocal = _AsyncLocal.Value = new CachedData();
  395. asyncLocal.Cache = value;
  396. }
  397. }
  398. }
  399. #endregion
  400. readonly AsyncCache<ScopeCache> _AsyncCache = new AsyncCache<ScopeCache>();
  401. ScopeCache AsyncScopeCache
  402. {
  403. get
  404. {
  405. return _AsyncCache.Value;
  406. }
  407. set
  408. {
  409. _AsyncCache.Value = value;
  410. }
  411. }
  412. #endregion
  413. public IServiceCollection rootServiceCollection { get; private set; }
  414. private IServiceProvider _rootServiceProvider;
  415. /// <summary>
  416. /// 请勿轻易设置,当serviceProvider为空时会自动创建
  417. /// </summary>
  418. public IServiceProvider rootServiceProvider
  419. {
  420. get => (_rootServiceProvider ?? (_rootServiceProvider = rootServiceCollection.BuildServiceProvider()));
  421. set => _rootServiceProvider = value;
  422. }
  423. IServiceScope CurScope => (AsyncScopeCache?.Scope);
  424. IServiceProvider CurServiceProvider => (AsyncScopeCache?.ServiceProvider) ?? (rootServiceProvider);
  425. #endregion
  426. #region class ScopeCache
  427. class ScopeCache : IDisposable
  428. {
  429. public IServiceProvider ServiceProvider = null;
  430. public IServiceScope Scope = null;
  431. Ioc ioc = null;
  432. ScopeCache parent = null;
  433. public void SetToLocal(Ioc ioc, IServiceScope Scope, IServiceProvider ServiceProvider)
  434. {
  435. this.ioc = ioc;
  436. this.Scope = Scope;
  437. this.ServiceProvider = ServiceProvider;
  438. lock (ioc)
  439. {
  440. parent = ioc.AsyncScopeCache;
  441. ioc.AsyncScopeCache = this;
  442. }
  443. }
  444. public void Dispose()
  445. {
  446. lock (ioc)
  447. {
  448. //need judje?
  449. if (ioc.AsyncScopeCache == this)
  450. {
  451. ioc.AsyncScopeCache = parent;
  452. }
  453. else
  454. {
  455. throw new Exception($"did not call IServiceScope.Dispose in order[Vit.Core.Util.Ioc,{ nameof(Ioc) }.cs,Line {GetFileLineNumber()}]");
  456. #region GetFileLineNumber
  457. int GetFileLineNumber()
  458. {
  459. System.Diagnostics.StackTrace st = new System.Diagnostics.StackTrace(1, true);
  460. return st.GetFrame(0).GetFileLineNumber();
  461. }
  462. #endregion
  463. }
  464. }
  465. }
  466. }
  467. #endregion
  468. public Ioc(IServiceCollection serviceCollection = null)
  469. {
  470. SetServiceCollection(serviceCollection);
  471. AddScoped<ScopeCache>();
  472. }
  473. public void SetServiceCollection(IServiceCollection serviceCollection = null)
  474. {
  475. rootServiceCollection = serviceCollection ?? new ServiceCollection();
  476. _rootServiceProvider = null;
  477. }
  478. public IServiceScope CreateScope()
  479. {
  480. var scope = CurServiceProvider.CreateScope();
  481. try
  482. {
  483. var provider = scope.ServiceProvider;
  484. var scopeData = provider.GetService<ScopeCache>();
  485. scopeData.SetToLocal(this, scope, provider);
  486. return scope;
  487. }
  488. catch (Exception)
  489. {
  490. scope.Dispose();
  491. throw;
  492. }
  493. }
  494. /// <summary>
  495. /// 请在注入后手动调用,否则所做的注入可能无效
  496. /// </summary>
  497. /// <returns></returns>
  498. public void Update()
  499. {
  500. _rootServiceProvider = null;
  501. }
  502. #endregion
  503. #region GetServiceDescriptor(s)
  504. /// <summary>
  505. ///
  506. /// </summary>
  507. /// <param name="serviceType"></param>
  508. /// <param name="lifetime"></param>
  509. /// <returns></returns>
  510. public List<ServiceDescriptor> GetServiceDescriptors(Type serviceType, ServiceLifetime lifetime)
  511. {
  512. var list = from serviceDescriptor in rootServiceCollection
  513. where serviceDescriptor.Lifetime == lifetime && serviceDescriptor.ServiceType == serviceType
  514. select serviceDescriptor;
  515. return list.ToList();
  516. }
  517. public ServiceDescriptor GetServiceDescriptor(Type serviceType, ServiceLifetime lifetime)
  518. {
  519. var list = GetServiceDescriptors(serviceType, lifetime);
  520. return list.LastOrDefault();
  521. //var lasts = list.TakeLast(1).ToList();
  522. //if (1 == lasts.Count)
  523. //{
  524. // return lasts[0];
  525. //}
  526. //return null;
  527. }
  528. #endregion
  529. #region Contains
  530. /// <summary>
  531. /// 检测是否有过注册
  532. /// </summary>
  533. /// <param name="serviceType">The <see cref="T:System.Type" /> of the service.</param>
  534. /// <param name="lifetime">The <see cref="T:Microsoft.Extensions.DependencyInjection.ServiceLifetime" /> of the service.</param>
  535. public bool Contains(Type serviceType, ServiceLifetime lifetime)
  536. {
  537. return 0 < GetServiceDescriptors(serviceType, lifetime).Count;
  538. }
  539. /// <summary>
  540. /// 检测是否有过注册
  541. /// </summary>
  542. /// <typeparam name="TService">The type of the service to add.</typeparam>
  543. /// <param name="lifetime">The <see cref="T:Microsoft.Extensions.DependencyInjection.ServiceLifetime" /> of the service.</param>
  544. public bool Contains<TService>(ServiceLifetime lifetime)
  545. {
  546. return Contains(typeof(TService), lifetime);
  547. }
  548. #endregion
  549. }
  550. }