5

问题陈述:实现一个允许相关程序集被覆盖的插件系统(避免文件锁定)。在 .Net 中,可能不会卸载特定程序集,只能卸载整个 AppDomain。

我发布这个是因为当我试图解决这个问题时,每个解决方案都提到了使用多个 AppDomain。多个 AppDomain 很难正确实现,即使是在项目开始时进行架构设计时也是如此。

此外,AppDomains 对我不起作用,因为我需要跨域传输类型作为 Speech Server worfklow 的 InvokeWorkflow 活动的设置。不幸的是,跨域发送类型会导致程序集被注入本地 AppDomain。

此外,这与 IIS 有关。IIS 有一个 Shadow Copy 设置,允许在加载到内存时覆盖正在执行的程序集。问题是(至少在 XP 下,没有在生产 2003 服务器上测试)当您以编程方式加载程序集时,卷影副本不起作用(因为您正在加载 DLL,而不是 IIS)。

4

3 回答 3

8
  1. 检查程序集是否已经加载(以避免由于一遍又一遍地加载相同的程序集而导致内存泄漏)。
  2. 如果未加载,则将程序集读入字节数组。这将防止锁定文件。
  3. 将字节数组作为参数提供给 Assembly.Load

以下代码假定您知道程序集的 FullName。

Assembly assembly = null;

foreach(Assembly loadedAssembly in AppDomain.CurrentDomain.GetAssemblies())
    if (loadedAssembly.FullName == "foobar, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null")
        assembly = loadedAssembly;

if(assembly == null)
{
    byte[] studybin = System.IO.File.ReadAllBytes(@"C:\pathToAssembly\foobar.dll");
    assembly = Assembly.Load(studybin);                
}

请注意,如果您尝试在目录中查找特定程序集,则可以运行“System.Reflection.AssemblyName.GetAssemblyName(path);” 查看 FullName 是否与您要查找的内容匹配。'GetAssemblyName(path)' 不会将程序集注入您当前的 AppDomain。

另请注意,此解决方案不适用于必须很少重新启动且程序集会频繁更改的应用程序。每次加载程序集时,应用程序的内存占用都会增加。没有卸载程序集的方法,因此减少内存使用的唯一选择是重新启动应用程序。但是,与使用多个应用程序域的大量性能、内存和代码复杂性开销相比,这种限制通常更可取。Type如果您希望使用s ,此限制也是不可避免的。

于 2009-01-19T18:54:12.777 回答
2

如果你想隔离你的插件,你必须...

  1. 创建一个扩展 MarshallByRefObject 的类型,它将与您的插件交互(我们称之为 FOOMASTER)
  2. 创建一个新的 appdomain(我们称之为 addinLand)
  3. 调用 addinLand.CreateInstanceAndUnwrap 在 addinLand 中创建 FOOMASTER 的实例,并获取当前应用域中的代理
  4. 告诉 FOOMASTER 加载您的插件

现在您的插件已加载到 addinLand 中,您可以通过您的 FOOMASTER 代理从您的主应用程序域与它们进行交互。当您的插件崩溃时,它们不会关闭您的应用程序。

这是一个有趣且略显混乱的过程。我最初认为这个想法是加载您的插件,然后将它们作为透明代理带入当前应用程序域,但最好的设计是将插件作为与您创建的更复杂类型交互的简单对象(FOOMASTER),扩展MarshallByRefObject,加载在 addinLand 应用程序域中,以及您与之交互的透明代理。

CLR Via C# 的第 21 章和第 22 章对理解该过程非常有帮助。

于 2009-07-20T15:39:08.790 回答
2

如果您对构建具有插件架构的系统的严肃方法感兴趣,您可能需要查看 MAF(托管插件框架),它现在是 .NET 框架的一部分,即 System.AddIn 命名空间。

它将帮助您管理插件隔离和版本控制,甚至与合同的向后兼容性。

虽然这里有一些学习曲线,所以这可能不是您正在寻找的。

http://msdn.microsoft.com/en-us/library/bb384200.aspx

于 2009-07-20T15:53:23.020 回答