diff --git a/sample/WebApi.Test.Unit/Program.cs b/sample/WebApi.Test.Unit/Program.cs
index 800a2407..89a30ab8 100644
--- a/sample/WebApi.Test.Unit/Program.cs
+++ b/sample/WebApi.Test.Unit/Program.cs
@@ -1,4 +1,3 @@
-using EasilyNET.Core.Misc;
using Serilog;
using Serilog.Events;
using Serilog.Sinks.OpenTelemetry;
@@ -10,7 +9,6 @@
#endif
Console.Title = $"❤️ {Constant.InstanceName}";
-AssemblyHelper.AddExcludeLibs("Npgsql.");
var builder = WebApplication.CreateBuilder(args);
// 配置Kestrel支持HTTP1,2,3
diff --git a/src/EasilyNET.Core/Misc/AssemblyHelper.cs b/src/EasilyNET.Core/Misc/AssemblyHelper.cs
index 31ca8790..2c0c058d 100644
--- a/src/EasilyNET.Core/Misc/AssemblyHelper.cs
+++ b/src/EasilyNET.Core/Misc/AssemblyHelper.cs
@@ -1,3 +1,6 @@
+using System.Collections.Concurrent;
+using System.Collections.Frozen;
+using System.Diagnostics;
using System.Reflection;
using System.Runtime.Loader;
using Microsoft.Extensions.DependencyModel;
@@ -10,52 +13,43 @@ namespace EasilyNET.Core.Misc;
///
/// 程序集帮助类
///
-// ReSharper disable once UnusedType.Global
public static class AssemblyHelper
{
- private static readonly HashSet Filters = ["dotnet-", "Microsoft.", "mscorlib", "netstandard", "System", "Windows", "PresentationUI"];
-
- ///
- /// 需要排除的项目
- ///
- private static readonly HashSet FilterLibs = [];
+ private static readonly ConcurrentDictionary AssemblyCache = [];
///
/// 构造函数
///
static AssemblyHelper()
{
- AllAssemblies = DependencyContext.Default?.GetDefaultAssemblyNames().Where(c => c.Name is not null && !Filters.Any(c.Name.StartsWith) && !FilterLibs.Any(c.Name.StartsWith)).Select(Assembly.Load);
- AllTypes = AllAssemblies.AsNotNull().SelectMany(c => c.GetTypes());
+ AllAssemblies = LoadAssemblies();
+ AllTypes = AllAssemblies.SelectMany(c => c.GetTypes());
}
///
/// 获取所有扫描到符合条件的程序集
///
- public static IEnumerable? AllAssemblies { get; }
+ public static IEnumerable AllAssemblies { get; }
///
/// 获取所有扫描到符合条件的程序集中的类型
///
- public static IEnumerable? AllTypes { get; }
-
- ///
- /// 添加排除项目,该排除项目可能会影响AutoDependenceInjection自动注入,请使用的时候自行测试.
- ///
- ///
- public static void AddExcludeLibs(params string[] names) => FilterLibs.AddRangeIfNotContains(names);
+ public static IEnumerable AllTypes { get; }
///
/// 根据程序集名字得到程序集
///
///
///
- public static IEnumerable GetAssembliesByName(params string[] assemblyNames) => assemblyNames.Select(o => AssemblyLoadContext.Default.LoadFromAssemblyPath(Path.Combine(AppContext.BaseDirectory, $"{o}.dll")));
+ public static IEnumerable GetAssembliesByName(params string[] assemblyNames)
+ {
+ return assemblyNames.Select(name => AssemblyLoadContext.Default.LoadFromAssemblyPath(Path.Combine(AppContext.BaseDirectory, $"{name}.dll")));
+ }
///
/// 查找指定条件的类型
///
- public static IEnumerable FindTypes(Func predicate) => AllTypes.AsNotNull().Where(predicate);
+ public static IEnumerable FindTypes(Func predicate) => AllTypes.Where(predicate);
///
/// 查找所有指定特性标记的类型
@@ -69,10 +63,72 @@ static AssemblyHelper()
///
///
///
- public static IEnumerable FindTypesByAttribute(Type type) => AllTypes.AsNotNull().Where(a => a.IsDefined(type, true)).Distinct();
+ public static IEnumerable FindTypesByAttribute(Type type) => AllTypes.Where(a => a.IsDefined(type, true)).Distinct();
///
/// 查找指定条件的类型
///
- public static IEnumerable FindAllItems(Func predicate) => AllAssemblies.AsNotNull().Where(predicate);
+ public static IEnumerable FindAllItems(Func predicate) => AllAssemblies.Where(predicate);
+
+ private static IEnumerable LoadAssemblies()
+ {
+ var assemblyNames = DependencyContext.Default?.GetDefaultAssemblyNames().Where(c => c.Name is not null).ToFrozenSet();
+ if (assemblyNames is null) yield break;
+ var batchSize = (int)Math.Ceiling((double)assemblyNames.Count / Environment.ProcessorCount); // 计算每组的大小
+ var loadedAssemblies = new ConcurrentBag();
+ if (assemblyNames.Count >= Environment.ProcessorCount)
+ {
+ var batches = assemblyNames.Select((name, index) => new { name, index })
+ .GroupBy(x => x.index / batchSize)
+ .Select(g => g.Select(x => x.name));
+ Parallel.ForEach(batches, batch =>
+ {
+ foreach (var assemblyName in batch)
+ {
+ LoadAssembly(assemblyName, loadedAssemblies);
+ }
+ });
+ }
+ else
+ {
+ foreach (var assemblyName in assemblyNames)
+ {
+ LoadAssembly(assemblyName, loadedAssemblies);
+ }
+ }
+ foreach (var assembly in loadedAssemblies)
+ {
+ yield return assembly;
+ }
+ }
+
+ private static void LoadAssembly(AssemblyName assemblyName, ConcurrentBag loadedAssemblies)
+ {
+ if (AssemblyCache.TryGetValue(assemblyName.FullName, out var cachedAssembly))
+ {
+ if (cachedAssembly is not null)
+ {
+ loadedAssemblies.Add(cachedAssembly);
+ }
+ return;
+ }
+ try
+ {
+ var assembly = Assembly.Load(assemblyName);
+ AssemblyCache[assemblyName.FullName] = assembly;
+ // 预检查程序集中的类型,确保可以加载
+ _ = assembly.GetTypes();
+ loadedAssemblies.Add(assembly);
+ }
+ catch (ReflectionTypeLoadException)
+ {
+ AssemblyCache[assemblyName.FullName] = null;
+ Debug.WriteLine($"无法加载程序集中的某些类型: {assemblyName.Name}, 将跳过.");
+ }
+ catch (Exception ex)
+ {
+ AssemblyCache[assemblyName.FullName] = null;
+ Debug.WriteLine($"加载程序集失败: {assemblyName.Name}, 错误: {ex.Message}");
+ }
+ }
}
\ No newline at end of file