C#运行时丢失程序集引用:IIS休眠后无法识别服务实现类
解答:IIS回收后丢失程序集引用的原因与修复方案
这个问题的核心是CLR的程序集延迟加载机制和IIS应用程序池回收的交互导致的,我来帮你拆解清楚:
为什么会出现这个问题?
当IIS因为长时间闲置暂停你的应用程序池时,整个AppDomain会被销毁。下次有请求进来时,新的AppDomain会初始化,但CLR默认只会按需加载程序集——只有当代码中直接引用了某个程序集里的类型时,这个程序集才会被加载到AppDomain中。
你第一次启动时能正常工作,是因为发布后的首次请求里,可能有隐式的代码路径触发了Services.dll和ServicesHU.dll的加载(比如注册逻辑里的间接引用)。但应用池回收后,新的AppDomain里没有这个触发点,AppDomain.CurrentDomain.GetAssemblies()自然扫不到这些未加载的程序集,也就找不到你的IVoucherService实现类,进而抛出"命名空间不存在"的错误。
具体的修复方案
1. 显式加载目标程序集
在你的服务注册逻辑(比如Application_Start)开头,手动加载需要的程序集,确保它们被加入到AppDomain中:
// 加载指定的服务程序集 var assemblyNames = new[] { "Services.dll", "ServicesHU.dll" }; var binDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin"); foreach (var name in assemblyNames) { var assemblyPath = Path.Combine(binDirectory, name); if (File.Exists(assemblyPath)) { Assembly.LoadFrom(assemblyPath); } }
提示:如果你的程序集不在bin目录下,记得调整路径到实际存放位置。
2. 确保程序集被正确复制到输出目录
先检查类库项目的发布配置:
- 右键
Services/ServicesHU项目 → 属性 → 生成 → 把"复制到输出目录"设置为始终复制或如果较新则复制 - 再检查Web项目对这些类库的引用:右键引用 → 属性 → 确保复制本地设置为
True,这样发布时这些DLL会自动同步到Web应用的bin目录
3. 优化扫描逻辑,不依赖已加载的程序集
把你的扫描逻辑改成直接从bin目录读取DLL文件,再加载检查类型,彻底避开延迟加载的问题:
private static Type GetServiceImplementedType<TService>() where TService : class { Type serviceType = typeof(TService); var binPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin"); var dllFiles = Directory.GetFiles(binPath, "*.dll"); foreach (var dllPath in dllFiles) { try { var assembly = Assembly.LoadFrom(dllPath); // 筛选出符合条件的实现类 var matchTypes = assembly.GetTypes() .Where(p => !p.IsInterface && serviceType.IsAssignableFrom(p)); foreach (var type in matchTypes) { var attributes = (ApiLocalizationAttribute[])type.GetCustomAttributes( typeof(ApiLocalizationAttribute), true); if (attributes != null && attributes.Any(a => a.Localization == Localization)) { return type; } } } catch (BadImageFormatException) { // 跳过非.NET程序集(比如原生DLL),继续扫描下一个 continue; } } return null; }
4. 调整IIS应用程序池设置减少回收频率
如果业务场景允许,可以调整IIS的应用程序池设置来减少回收次数:
- 打开IIS管理器 → 找到你的应用程序池 → 高级设置
- 延长闲置超时(分钟),比如从默认的20分钟改成更大的值
- 确保启用32位应用程序的设置和你的程序集架构匹配
- 检查加载用户配置文件是否设为
True,避免权限问题导致程序集无法加载
额外小贴士
- 扫描时可以通过文件名过滤(比如只加载以
Services开头的DLL),避免加载不必要的第三方DLL,提升性能 - 如果用了依赖注入容器(比如Autofac、Microsoft DI),直接用容器自带的程序集扫描功能,它们已经处理了程序集加载的细节,比手动扫描更可靠
内容的提问来源于stack exchange,提问作者Smiley
相关产品推荐
相关产品推荐

