.NET8 WebAPI加载SqlGuidCaster类型失败,求解决方案
解决.NET8中遍历程序集类型时出现的SqlGuidCaster加载失败问题
问题原因
.NET 8 对程序集加载和内部类型访问的控制更加严格,Microsoft.Data.SqlClient(或System.Data.SqlClient)这类库包含一些内部实现类型(如SqlGuidCaster),这些类型要么通过类型转发机制指向其他程序集,要么仅在特定运行时场景下可用。当你通过DependencyContext.Default加载所有运行时程序集并遍历所有类型时,会触发这些内部类型的加载,而它们的依赖未被正确初始化或部署,导致类型加载失败。这种问题在.NET 6中不存在,是因为.NET 6的程序集加载策略对内部类型的访问限制更宽松。
解决方案
1. 排除不需要遍历的第三方程序集
如果你不需要处理Microsoft.Data.SqlClient这类第三方库的类型,直接在加载程序集时排除它们:
var builder = WebApplication.CreateBuilder(args); var list = DependencyContext.Default.RuntimeLibraries.ToList(); var assemblies = list // 排除SQL客户端相关程序集 .Where(m => !m.Name.Equals("Microsoft.Data.SqlClient", StringComparison.OrdinalIgnoreCase) && !m.Name.Equals("System.Data.SqlClient", StringComparison.OrdinalIgnoreCase)) .Select(m => { try { return AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(m.Name)); } catch { return null; } }) .Where(m => m != null) .ToList(); foreach (var assembly in assemblies) { foreach (var type in assembly.GetTypes()) { } } app.Run();
2. 遍历类型时捕获并跳过加载失败的类型
如果必须加载所有程序集,可在获取类型时捕获ReflectionTypeLoadException,跳过无法加载的类型:
var builder = WebApplication.CreateBuilder(args); var list = DependencyContext.Default.RuntimeLibraries.ToList(); var assemblies = list .Select(m => { try { return AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(m.Name)); } catch { return null; } }) .Where(m => m != null) .ToList(); foreach (var assembly in assemblies) { Type[] types; try { types = assembly.GetTypes(); } catch (ReflectionTypeLoadException ex) { // 仅保留成功加载的类型 types = ex.Types.Where(t => t != null).ToArray(); } foreach (var type in types) { // 执行你的逻辑 } } app.Run();
3. 仅加载你需要的程序集(推荐)
避免加载所有运行时程序集,只加载你自己的项目程序集或特定业务相关的程序集,减少不必要的类型加载:
var builder = WebApplication.CreateBuilder(args); var currentAssembly = Assembly.GetExecutingAssembly(); var currentAssemblyName = currentAssembly.GetName().Name; var list = DependencyContext.Default.RuntimeLibraries.ToList(); var assemblies = list // 仅加载当前项目和自定义业务程序集(替换为你的命名空间前缀) .Where(m => m.Name.Equals(currentAssemblyName, StringComparison.OrdinalIgnoreCase) || m.Name.StartsWith("YourBusinessNamespace", StringComparison.OrdinalIgnoreCase)) .Select(m => { try { return AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(m.Name)); } catch { return null; } }) .Where(m => m != null) .ToList(); foreach (var assembly in assemblies) { foreach (var type in assembly.GetTypes()) { } } app.Run();
内容的提问来源于stack exchange,提问作者Jin Lyu
相关产品推荐
相关产品推荐

