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

时间:2014-04-12 20:54:58

标签: c# .net .net-assembly dynamic-loading

我的C#应用​​程序server.exe对我的业务运营至关重要,理想情况下需要24/7不间断地运行。代码是坚如磐石的,但是我无法控制的一件事是由第三方生成的入站数据源质量差。我偶尔会收到包含异常的数据Feed,在这种情况下我必须:

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

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

我的目标:将Feed处理代码隔离到一个单独的DLL中,其内容可以在不重新启动server.exe的情况下进行更新。我该如何做?

请允许我在撰写此论坛帖子之前解释我迄今所做的工作:

Feed步骤已移至名为common.dll的新程序集。界面看起来像这样:

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

Server.exe现在引用common.dll

Feed进程本身已移至名为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的类,用于根据某些配置输入创建特定的Feed处理程序。它看起来像这样:

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执行。

我从哪里开始?

3 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分:1)

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

我建议您在进行时调查并提出问题。

答案 2 :(得分:1)

除了卷影复制选项之外,您还应创建一个AppDomain并检查更改dll以重新启动域reload the dll,然后使用FileSystemWatcher进行检查。

照顾not directly referencing your classes between AppDomains,否则您的旧装配将永远不会被卸下。