dotnet程序的动态加载一:Assembly.Load
如何去动态加载一些主程序框架并不知道(没有引用)的组件呢?以下给出几个方法并作相关讨论。
一、使用Assembly.Load。
范例代码:下载
我们先准备一些接口(interface),主程序会不断的在他认为需要的时候调用这些接口。并有可能某些接口的调用还依赖于其他接口。但主程序并不关心这些接口谁来实现。好了,我们先创建一个类库(我命名他为DomainBase)来保存这些接口。以下是我们定义的第一个接口
{
string SayHello();
}
创建我们的主程序,我创建用了一个windows的程序DomainTest,引用上面的类库项目DomainBase
{
public Form1()
{
InitializeComponent();
}
private void addLog(string msg)
{
this.textBox1.AppendText(string.Format("{0}\n", msg));
}
private void btnRef_Click(object sender, EventArgs e)
{
DomainBase.IDo myDo = buildDoActor();
if (myDo != null)
{
string words = myDo.SayHello();
this.addLog(words);
}
}
private DomainBase.IDo buildDoActor()
{
return null;
}
}
这里buildDoActor我没有写完,实现的做法是读取配置信息,得到配置的字符信息再动态去创建相关类的实例。但为了演示能简单化,我把相关信息直接写赋值给一些字符变量。我们再创建一个类库项目(我命名为HelloLibrary),同样引用DomainBase项目,再添加一个实现了DomainBase.IDO接口的类:Hello,代码如下:
{
#region IDo 成员
public string SayHello()
{
return "Hello. I am HelloLibray.Hello.";
}
#endregion
}
{
string assemblyName = "HelloLibrary";//实际情况应从配置中获取。
string className = "HelloLibrary.Hello";//实际情况应从配置中获取。
Assembly assembly = Assembly.Load(assemblyName);
object obj = assembly.CreateInstance(className);
if (obj == null)
{
this.addLog("未能创建Hello");
return null;
}
DomainBase.IDo myDo = obj as DomainBase.IDo;
if (myDo == null)
this.addLog("没有实现IDO");
return myDo;
}
编译各项目,并把HelloLibrary.dll拷贝到Form程序的运行目录下(我把三个项目生成的输出路径都设置了统一的一个目录,所以可以省却这一步),运行windows程序,text1就会显示“Hello. I am HelloLibray.Hello.”
windows的主程序并不知道HelloLibray的存在(没有引用HelloLibray.dll),只引用了DomainBase.dll,却调用了HelloLibray.Hello的相关方法。HelloLibray可以任意的被其他dll去替代,只要拷贝相关实现了IDO类库的dll和修改配置表。当然以上例子我简化了这一过程,实际开发时应从配置表(如app.config)去读取相关信息。
不过这有一个问题存在。举个例子,我想修改Hello.SayHello方法,将当前的版本号也一并输出。
{
return "Hello. I am HelloLibray.Hello, v1.0.";
}
我生成该类库的dll,当windows程序运行时,我是没法将这个新的dll替换运行目录上旧的HelloLibray.dll,操作系统会告诉你“无法复制HelloLibray.dll,程序正在被另一个为或程序使用”。因为我所有项目的生成都输出都一个目录,主程序运行时,我生成HelloLibray时,IDE提示我
当然,我们关闭主程序,更新好再运行就可以了。
本想放在一些图片的,无奈网速不好,每个打开图片,显示一堆旧图片有困难,更别想去上传了。编辑好的内容都会掉失,因浮动层的关闭按键没显示,久久关闭不了,只好擦新。