You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:55:05