问题陈述:实现一个插件系统,允许覆盖关联的程序集(避免文件锁定).在.Net中,可能无法卸载特定程序集,只能卸载整个AppDomain.
我发布这个是因为当我试图解决问题时,每个解决方案都参考了使用多个AppDomain.即使在项目开始时进行架构,多个AppDomain也很难正确实现.
此外,AppDomains对我不起作用,因为我需要跨域传输Type作为Speech Server worfklow的InvokeWorkflow活动的设置.不幸的是,跨域发送类型会导致程序集注入本地AppDomain.
此外,这与IIS相关.IIS具有卷影复制设置,允许执行程序集在加载到内存时被覆盖.问题是(至少在XP下,没有在生产2003服务器上测试)当您以编程方式加载程序集时,卷影副本不起作用(因为您正在加载DLL,而不是IIS).
检查组件是否已加载(以避免因反复加载同一组件而导致内存泄漏).
如果未加载,请将程序集读入字节数组.这样可以防止锁定文件.
将字节数组作为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,这种限制也是不可避免的.