【问题标题】:How can I get a portion of my C# app to load dynamically without app restart?如何让我的 C# 应用程序的一部分在不重新启动应用程序的情况下动态加载?
【发布时间】:2014-05-26 23:47:59
【问题描述】:

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

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

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

我的目标:将提要处理代码隔离到一个单独的 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 的类,用于根据一些配置输入创建特定的提要处理器。它看起来像这样:

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 中执行,而不是旧的。

我从哪里开始?

【问题讨论】:

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


【解决方案1】:

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

【讨论】:

  • 有趣。谢谢。因此,假设我使用 Assembly.Load(byte[]) 动态加载我的程序集。我从其他 SO 帖子中收集到,一旦我加载它,我就无法在不杀死整个 AppDomain 的情况下卸载它,这在我的情况下是不可行的。那么您是说如果我的程序确定feedProcessor.dll 已过时,我可以随后 调用Assembly.Load() 吗?之前加载的版本怎么办?我是否取消对它的引用?没有 Dispose() 函数。我会造成内存泄漏吗?
【解决方案2】:

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

我建议您在进行过程中进行调查并提出问题。

【讨论】:

    【解决方案3】:

    除了卷影复制选项,您应该创建一个 AppDomain 并检查何时更改您的 dll 以重新启动域和reload the dll,您可以使用FileSystemWatcher 进行检查。

    照顾好not directly referencing your classes between AppDomains,否则你的旧程序集永远不会被卸载。

    【讨论】:

      猜你喜欢
      • 2019-12-15
      • 2017-08-13
      • 2014-07-21
      • 1970-01-01
      • 2019-08-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多