Assembly.Load(byte[])只加载一次

本文关键字:加载 一次 Load byte Assembly | 更新日期: 2023-09-27 18:15:54

这可能看起来像一个重复,但它不是,它实际上是一个不同的问题!

这个场景是这样的:我有一个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。我可以用汇编。LoadFrom或LoadFile,以避免此问题,但随后我会锁定我不想要的文件,因为我希望能够删除它。

另一种选择是使用一个新的应用程序域来加载它们,调用方法并卸载它们,但然后我还必须加载该域中的接口dll,我真的不知道它在web应用程序中的路径。更不用说将数据从一个应用程序域移动到另一个应用程序域是一种痛苦,而且很难完成。

第三个选择是使用一个影子拷贝,但是这样我就不能删除这个影子拷贝了。

选项?基本上我需要的是,加载dll,使用它,卸载它,继续。

Assembly.Load(byte[])只加载一次

如果你真的需要卸载它,你别无选择,只能使用一个单独的应用程序域(参见如何从主应用程序域卸载程序集?例如)

如果你只需要加载每个程序集一次,但不关心卸载旧的程序集,你需要自己管理跟踪哪些程序集被加载。要做到这一点,最简单的方法是在加载每个文件之前对其进行散列。比如:

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();
}

如果你想对项目进行版本化,另一种方法是在你的接口中添加一些元数据。