我有一个无法修改的.dll库,它带有使用许多静态变量和单例实例的类。现在,我需要所有这些类的第二个实例,并且需要一些解决方案,该解决方案可以在某个类的实例之间隔离静态变量,而无需更改程序集的任何其他属性。
第二次加载相同的程序集实际上并没有再次加载,但是我发现将其读取到字节数组然后加载,实际上解决了一半问题:
lib.dll:
namespace lib
{
public class Class1 : ILib
{
private static int i;
public int DoSth()
{
return i++;
}
public string GetPath()
{
return typeof(Class1).Assembly.Location;
}
}
}
app.exe:
namespace test
{
public interface ILib
{
int DoSth();
string GetPath();
}
class Program
{
static void Main()
{
var assembly1 = Assembly.LoadFile(Path.GetFullPath(".\\lib.dll"));
var instance1 = (ILib)assembly1.CreateInstance("lib.Class1");
Console.WriteLine(instance1.GetPath());
Console.WriteLine(instance1.DoSth());
Console.WriteLine(instance1.DoSth());
var assembly2 = Assembly.LoadFile(Path.GetFullPath(".\\lib.dll"));
var instance2 = (ILib)assembly2.CreateInstance("lib.Class1");
Console.WriteLine(instance2.GetPath());
Console.WriteLine(instance2.DoSth());
Console.WriteLine(instance2.DoSth());
var assembly3 = AppDomain.CurrentDomain.Load(File.ReadAllBytes("lib.dll"));
var instance3 = (ILib)assembly3.CreateInstance("lib.Class1");
Console.WriteLine(instance3.GetPath());
Console.WriteLine(instance3.DoSth());
Console.WriteLine(instance3.DoSth());
Console.Read();
}
}
}
此返回:
C:\bin\lib.dll
0
1
C:\bin\lib.dll
2
3
0
1
静态变量已重新启动,但不幸的是,下一个问题是库中使用的程序集位置为空。
我想避免将库加载到其他AppDomain,因为它会给跨域代码带来太多问题;有些类无法序列化。
我想避免物理上将库复制到磁盘上。
我想避免IL编织并使用Mono.Cecil或类似方法,因为这太过分了。
将程序集加载到单独的AppDomain或单独的进程中只是您的明智选择。处理跨域/跨进程的通信,或者获取没有遇到问题的库版本。