这看起来像是重复但不是,它实际上是一个不同的问题!
场景是这样的:我有一个Web应用程序,它遍历动态加载到系统中的所有dll,以从中访问方法并获取数据。这些dll是由网站用户添加的。
伪代码会是这样的:
pulic void GetNews(){
foreach(var i in ListOfDllPaths){
Assembly dll = Assembly.Load( File.ReadAllBytes(i));
SomeInterface if = CreateInstance(dll); //This methods does all the validation and such
if.DoMethod();
}
}
现在的问题是,每次调用GetNews()时,都会重新加载相同的dll,同时加载相同的dll。 我可以使用Assembly.LoadFrom或LoadFile来避免这个问题,但后来我会锁定我不想要的文件,因为我希望能够删除它。
另一种选择是使用新的应用程序域来加载它们,调用方法并卸载它们,但是我还要在该域中加载接口dll,我真的不知道它的路径网络应用程序。更不用说将数据从一个应用程序域移动到另一个应用程序域是一件痛苦的事情,而且难以实现。
三分之一的选择是使用卷影副本,但后来我无法删除卷影副本相同的结果。
选项?基本上我需要的是,加载DLL,使用它,卸载它,继续前进。
答案 0 :(得分:3)
如果您需要真正卸载它,您别无选择,只能使用单独的应用程序域(例如,请参阅How to unload an assembly from the primary AppDomain?)
如果您只需要加载每个组件一次,但不关心卸载旧组件,则需要管理以跟踪自己加载哪些组件。任何简单的方法都是在加载之前获取每个文件的哈希值。喜欢的东西:
Dictonary<string,bool> loadedAssemblies = new Dictonary<string,bool>();
using(SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider())
{
var hash = Convert.ToBase64String(sha1.ComputeHash(byteArray));
if(loadedAssemblies.ContainsKey(hash)) continue;
loadedAssemblies[hash] = true;
Assembly dll = Assembly.Load( File.ReadAllBytes(i));
SomeInterface if = CreateInstance(dll); //This methods does all the validation and such
if.DoMethod();
}
如果您想要版本项目,另一种方法是向您的界面添加一些元数据。