c# - 如何在不使用 AppDomains 的情况下实现 .net 插件?

标签 c# .net iis assemblies appdomain

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

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

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

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

最佳答案

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

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

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)”不会将程序集注入(inject)您当前的 AppDomain。

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

关于c# - 如何在不使用 AppDomains 的情况下实现 .net 插件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/458699/

相关文章:

iis - 调用网页的尽可能简单的任务计划

asp.net - 将非 www 重定向到 www。使用 URL 重写 2.0

c# - 我可以看到所有 View 在 Visual Studio 2012 MVC 4 App 中是如何内部链接的吗?

c# - ExpandoObject 的动态 LINQ 查询?

c# - VS2010 - 如何在第一次编译错误时自动停止编译

mysql - 不允许主机 x 连接到此 mysql 服务器

php - PHP 网站的最佳 XML DB?

c# - 如何在 C# 中序列化/反序列化可选的 XML 枚举?

.net - F#函数匹配

.net - 由于 .net MVC 中的 HttpContext,测试我的 Controller 引发错误