但是,如果遇到引用DLL?如何卸载被引用的程序集,基本上陷入困境。
网上资料无非 appdomain能解决。但是,不算性能损失,调用方式不便。
这种繁琐的解决方案,估计也不会经常在项目中实施,除非非它不可。
当然,一开始就注重设计,引入工厂容器进行对象管理之类项目排除。
这里,我们来演示一个小小的项目,或许,对你有所帮助。
首先要说的是:AssemblyResolve
当你尝试用Assembly.Load载入一个程序集,并且尝试运行其中方法的时候。如果遇到引用另外一个程序集的情况下,AssemblyResolve就出场了。
你可以像这样使用它。
static List<Assembly> AssemblyList = new List<Assembly>();
static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
foreach (var item in AssemblyList)
{
if (item.ToString() == args.Name)
{
return item;
}
}
return null;
}不管程序集在那个地方,但是,请不要放在loader目录下。
首先,要做的是重定向程序集,这一步我们已经做完了。(下面砸鸡蛋,下去,这么菜的。。。。,顶住压力楼主继续。。。)
好吧,然后是关于程序集锁定的问题,像这样:
AssemblyList.Add(Assembly.Load( System.IO.File.ReadAllBytes(item.FullName)));
以下是伪代码,不一定能跑,大家看那么个意思。
DLL A:
public class ClassA
{
public ClassA()
{
Console.WriteLine("我是A");
}
}
保存,然后通过放射调用。 这个当然没问题。
byte[] buffer = System.IO.File.ReadAllBytes(@"lib1.dll");
System.Reflection.Assembly.Load(buffer).CreateInstance("ClassA");
ok,完成第一步,加强以下,
DLL B:
public class ClassB
{
public ClassB()
{
Console.WriteLine("我是B");
}
public void TestB()
{
Console.WriteLine("TestB");
}
}
修改DLLA
public ClassA()
{
Console.WriteLine("我是A");
Console.WriteLine("运行DLLB");
new ClassB().TestB();
}
再次反射运行,ok 没问题。。
然后,重头戏,你需要把你的运行代码修改下,加入一个循环,像这样:
while(true)
{
byte[] buffer = System.IO.File.ReadAllBytes(@"lib1.dll");
System.Reflection.Assembly.Load(buffer).CreateInstance("ClassA");
Thread.Sleep(3000);
}
3秒调用一次,让他独立运行。
然后,在运行的时候,我们修改DLLA,
public ClassA()
{
Console.WriteLine("我是A,动态修改。。");
}
编译,回来看测试程序,貌似没什么问题。(众人继续鸡蛋。。。废话。。。)
修改DLLB
Console.WriteLine("我是B,动态运行");
编译,继续看测试。貌似没什么改变。
重点来了,这里就是我们要解决的问题,
如果跟踪AssemblyResolve方法,会发现,第二次载入的时候,并没有触发,
也就是说,dllb 一直在内存中,如何卸载,说实话,我也不会卸载(众人发火,下去下去。。。。)
不过,咱可以替换掉。(凑合,如果不行,拍死你。。)
我们要改的只有一点点,修改dllb的版本号,然后重新编译dlla,以及dllb
然后如果不出意外的话,你已经在测试程序中看到你想要的结果了。
(众人,再说不就完了,那么多废话,继续鸡蛋伺候,鸡蛋贵啊,,少丢点。。)
谢谢观赏 - -!
本文探讨了在C#中如何处理引用DLL的卸载问题,指出Appdomain虽是解决方案但存在性能损失和不便。通过示例展示了一个利用AssemblyResolve事件重定向程序集的方法,演示了动态加载与替换DLL的过程,强调通过修改DLL版本号实现程序集的更新,以达到在运行时动态更新代码的效果。
3768

被折叠的 条评论
为什么被折叠?



