C#丢弃Appdomain 之 动态dll替换

来源:互联网 发布:野生动物灭绝数据2016 编辑:程序博客网 时间:2024/04/30 05:02
    好久没写什么了,最近项目遇到一要求,为开发方便,需要wcf 服务能动态加载。这本不是什么难事,反射内存加载大家都会。

     但是,如果遇到引用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(都快睡着了。。。)

以下是伪代码,不一定能跑,大家看那么个意思。


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

然后如果不出意外的话,你已经在测试程序中看到你想要的结果了。

(众人,再说不就完了,那么多废话,继续鸡蛋伺候,鸡蛋贵啊,,少丢点。。)

谢谢观赏 - -!



原创粉丝点击