如何在不重新启动应用程序的情况下动态加载C#应用程序的一部分

本文关键字:应用程序 动态 加载 一部分 情况下 重新启动 | 更新日期: 2023-09-27 17:58:00

我的C#应用程序server.exe对我的业务运营至关重要,理想情况下需要全天候无中断运行。代码坚如磐石,但有一件事我无法控制,那就是第三方生成的入站数据源质量很差。我偶尔会收到包含异常的数据馈送,在这种情况下我必须:

  • 更新server.exe内的馈送处理代码以适应异常
  • 重新编译
  • 使用新代码重新启动server.exe,并允许处理语法有缺陷的提要

整个过程通常不到几分钟,但server.exe的重新启动会导致某些非关键状态信息的重置,更糟的是,会导致依赖server.exe. 的外部过程中断

我的目标:将提要处理代码隔离到一个单独的DLL中,该DLL的内容可以在不重新启动server.exe的情况下更新我该怎么做?

请允许我解释一下我在写这个论坛帖子之前做了什么:

馈送处理器接口已移动到一个名为common.dll的新程序集。界面看起来像这样:

public interface IFeedProcessor{
    bool ProcessFeed(String filePath);  //returns false on failure, true on success
}

Server.exe现在引用common.dll

饲料处理器本身已被转移到一个名为feedProcessors.dll的新组件中。实现看起来像这样:

internal class FeedProcessor1:IFeedProcessor{
    public FeedProcessor1(){}
    bool ProcessFeed(String filePath){/*implementation*/return true;}
}
internal class FeedProcessor2:IFeedProcessor{
    public FeedProcessor2(){}
    public bool ProcessFeed(String filePath){/*implementation*/return true;}
}
[... and so on...]

feedProcessors.dll还包含一个名为FeedProcessorUtils的类,用于根据一些配置输入创建特定的提要处理器。它看起来像这样:

public class FeedProcessorUtils{
    public static void CreateFeedProcessor(int feedType /*and other configuration params*/){
        switch(feedType){
            case 1:return new FeedProcessor1();
            case 2:return new FeedProcessor2();
            default: throw new ApplicationException("Unhandled feedType: "+feedType);
        }
    }
}

一切都和以前一样,但它当然不能解决我的动态加载问题;如果我用新代码更新了feedProcessors.dll并将其复制到生产服务器,我将无法执行此操作,因为该文件正在使用中。这并不奇怪。那么解决方案是什么呢?

理想情况下,我希望能够将更新的feedProcessors.dll复制到生产服务器,而不会出现文件使用错误,也不会重新启动server.exe。然后,下次server.exe调用FeedProcessorUtils.CreateFeedProcessor()时,它将从我的修订的DLL执行,而不是从旧的DLL执行。

我从哪里开始?

如何在不重新启动应用程序的情况下动态加载C#应用程序的一部分

您希望为动态加载的DLL使用卷影复制程序集http://msdn.microsoft.com/en-us/library/ms404279(v=vs.110).aspx

听起来像是使用MEF的经典场所:http://msdn.microsoft.com/en-us/library/dd460648(v=vs.110).aspx

我建议你调查一下,并在进行过程中提出问题。

除了卷影复制选项外,您还应该创建一个AppDomain并在更改dll时进行检查,以重新启动域并重新加载dll,您可以使用FileSystemWatcher进行检查。

注意不要在AppDomains之间直接引用您的类,否则您的旧程序集将永远不会被卸载。