设为首页收藏本站Access中国

Office中国论坛/Access中国论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

返回列表 发新帖
查看: 2757|回复: 1
打印 上一主题 下一主题

【原创】用C#动态装卸DLL文件

[复制链接]
跳转到指定楼层
1#
发表于 2014-2-22 16:26:13 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

上一个以前用过项目中的简化案例,
为了控制进程间通讯,实际情况要复杂的多:


[1]接口

  • namespace MyAddin  
  • {  
  •     public interface IAddin  
  •     {  
  •         void PrintName();  
  •     }  
  • }  


[2]dll文件
  • using System;  
  • namespace MyAddin  
  • {  
  •     public class Addin : MarshalByRefObject, IAddin  
  •     {  
  •         private const string name = "My name is addin-01!";  
  •         public void PrintName()  
  •         {  
  •             Console.WriteLine(name);  
  •         }  
  •     }  
  • }  



[3]主域
  • using System;  
  • using System.IO;  
  • namespace MyAddin  
  • {  
  •     class Program  
  •     {  
  •         static void Main()  
  •         {  
  •             //开始  
  •             Console.WriteLine("Begin!");  
  •             //准备工作:得到插件路径  
  •             string pathNameOfAddin = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "MyAddin.dll");  
  •             //构建AppDomainSetup实例     
  •             AppDomainSetup setup = new AppDomainSetup();  
  •             setup.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;  
  •             setup.ShadowCopyFiles = "true";  
  •             //装载AppDomainOfAddin     
  •             AppDomain appDomainOfAddin = AppDomain.CreateDomain("AppDomainOfAddin", null, setup);  
  •             //调用AppDomainOfAddin  
  •             IAddin myAddin = (IAddin)appDomainOfAddin.CreateInstanceFromAndUnwrap(pathNameOfAddin, "MyAddin.Addin");  
  •             myAddin.PrintName();  
  •             //卸载AppDomainOfAddin     
  •             AppDomain.Unload(appDomainOfAddin);  
  •             //删除AppDomainOfAddin  
  •             File.Delete(pathNameOfAddin);  
  •             Console.WriteLine(pathNameOfAddin+(File.Exists(pathNameOfAddin) ? "删除失败!" : "删除成功!"));  
  •             //结束  
  •             Console.ReadKey();  
  •         }  
  •     }  
  • }  



//输出:
//Begin!
//My name is addin-01!
//F:/开发项目/临时区间/SolutionNew/Test/bin/Debug/MyAddin.dll删除成功!



分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享分享 分享淘帖 订阅订阅
2#
 楼主| 发表于 2014-2-22 16:27:29 | 只看该作者
如果你对对布式对象有一定的了解,实现这种“动态插件”的方案并不困难,
做一些补充和说明:
一般情况下,插件应该满足的条件(当然,还有再包装的技术,本质上还是一样的):

[1]继承MarshalByRefObject
[2]参数类型及返回值的类型是可序列化的

得弄清楚三种对象的概念
[1]本地对象:
.net对象在默认情况下是本地的,在创建对象的进程之处,普通的对象是不能被访问的。
[2]固定对象:
对象从不移动,对象总是按引用传递的,通过这个引用,其它计算机可以与对象进行交互。
[3]不固定对象:
对象可以在进程音或计算机间按值传递,对象从原来的进程或计算机被复制到其他的进程或计算机上。

总体思路:
[1]根源:Assembly类有天然的缺陷,就是没有UnLoad操作。
[2]方案:替代品,AppDomain中有UnLoad操作。
[3]本质:进程中的不同的AppDomain之间的通信,其实是基于Remoting的,我的案例中虽然没有出现Remoting
其实在这里被隐藏了:
IAddin myAddin = (IAddin)appDomainOfAddin.CreateInstanceFromAndUnwrap(pathNameOfAddin, "MyAddin.Addin");
CreateInstanceFromAndUnwrap语句就是实现两个程序域之间通讯的关键,本质上还是Remoting的方案。
因为Loader类是在主程序域中,RemoteLoader类则是在子程序域中。实际上是在主程序域中调用Addin的。
因此须要使用代理的方式,来获得对象的引用,就是上述的[2]固定对象方式,
[4]基于Remoting本身的要求(下面稍作解释),得到上述的两个要求:
A:继承MarshalByRefObject
B:参数类型及返回值的类型是可序列化的
关于Remoting
[1].NET FRAMEWORK包括REMOTING子系统,使得.NET应用程序可以交互,当然包括域。
[2]Remoting依赖于“固定对象”和“不固定对象”两个概念
[3]Remoting有上下文的概念,包括以下概念:Channel/格式化/listener/对象代理和位置透明机制
注意:表面上是跑题了,实际上只要有了Remoting的概念,实现这种“插件”机制真的是非常容易理解的。


最后,建议看一本书书
《VB.NET业务对象专家指南》
只要通读全书,这种插件机的实在是小菜一碟了~~
您需要登录后才可以回帖 登录 | 注册

本版积分规则

QQ|站长邮箱|小黑屋|手机版|Office中国/Access中国 ( 粤ICP备10043721号-1 )  

GMT+8, 2024-5-7 19:58 , Processed in 0.092008 second(s), 25 queries .

Powered by Discuz! X3.3

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表