如何在不使用 AppDomains 的情况下实现 .net 插件? [英] How do I implement .net plugins without using AppDomains?

查看:31
本文介绍了如何在不使用 AppDomains 的情况下实现 .net 插件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Problem statement: Implement a plug-in system that allows the associated assemblies to be overwritten (avoid file locking). In .Net, specific assemblies may not be unloaded, only entire AppDomains may be unloaded.

我发布这个是因为当我试图解决这个问题时,每个解决方案都参考了使用多个 AppDomains.多个 AppDomain 很难正确实现,即使在项目开始时就已构建.

I'm posting this because when I was trying to solve the problem, every solution made reference to using multiple AppDomains. Multiple AppDomains are very hard to implement correctly, even when architected at the start of a project.

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

Also, AppDomains didn't work for me because I needed to transfer Type across domains as a setting for Speech Server worfklow's InvokeWorkflow activity. Unfortunately, sending a type across domains causes the assembly to be injected into the local AppDomain.

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

Also, this is relevant to IIS. IIS has a Shadow Copy setting that allows an executing assembly to be overwritten while its loaded into memory. The problem is that (at least under XP, didnt test on production 2003 servers) when you programmatically load an assembly, the shadow copy doesnt work (because you are loading the DLL, not IIS).

推荐答案

  1. 检查程序集是否已经加载(避免因反复加载同一个程序集而导致内存泄漏).
  2. 如果未加载,则将程序集读入字节数组.这将防止锁定文件.
  3. 将字节数组作为参数提供给 Assembly.Load

以下代码假设您知道程序集的全名.

The following code assumes you know the FullName of an assembly.

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.

Note that if you are trying to find a specific assembly in a directory, you can run 'System.Reflection.AssemblyName.GetAssemblyName(path);' to see if the FullName matches what you are looking for. 'GetAssemblyName(path)' does NOT inject the assembly into your current AppDomain.

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

Also note that this solution is not appropriate for applications that must only rarely restart AND the assemblies change with high frequency. Every time an assembly is loaded, the memory footprint of you application will grow. There is no method to unload an assembly, thus the only option to shrink memory usage is to restart the application. However, this limitation is often preferable to the large performance, memory, and code complexity overhead of using multiple app domains. This limitation is also unavoidable if you wish to work with Types.

这篇关于如何在不使用 AppDomains 的情况下实现 .net 插件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆