dotnet程序的动态加载一:Assembly.Load

如何去动态加载一些主程序框架并不知道(没有引用)的组件呢?以下给出几个方法并作相关讨论。


一、使用Assembly.Load。

范例代码:下载


我们先准备一些接口(interface),主程序会不断的在他认为需要的时候调用这些接口。并有可能某些接口的调用还依赖于其他接口。但主程序并不关心这些接口谁来实现。好了,我们先创建一个类库(我命名他为DomainBase)来保存这些接口。以下是我们定义的第一个接口

public interface IDo
{
    
string SayHello();
}

创建我们的主程序,我创建用了一个windows的程序DomainTest,引用上面的类库项目DomainBase

代码
public partial class Form1 : Form
{
    
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,代码如下:

public class Hello : DomainBase.IDo
{
    
#region IDo 成员
    
public string SayHello()
    {
        
return "Hello. I am HelloLibray.Hello.";
    }
    
#endregion
}
现在来写Form1未完成的buildDoActor方法
private DomainBase.IDo buildDoActor()
{
    
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方法,将当前的版本号也一并输出。

public string SayHello()
{
    
return "Hello. I am HelloLibray.Hello, v1.0.";
}

 

 

我生成该类库的dll,当windows程序运行时,我是没法将这个新的dll替换运行目录上旧的HelloLibray.dll,操作系统会告诉你“无法复制HelloLibray.dll,程序正在被另一个为或程序使用”。因为我所有项目的生成都输出都一个目录,主程序运行时,我生成HelloLibray时,IDE提示我

错误    3    无法将文件“obj\Debug\HelloLibrary.dll”复制到“..\bin\HelloLibrary.dll”。文件“..\bin\HelloLibrary.dll”正由另一进程使用,因此该进程无法访问该文件。    HelloLibrary

 

当然,我们关闭主程序,更新好再运行就可以了。


本想放在一些图片的,无奈网速不好,每个打开图片,显示一堆旧图片有困难,更别想去上传了。编辑好的内容都会掉失,因浮动层的关闭按键没显示,久久关闭不了,只好擦新。






 

posted @ 2010-01-08 09:35  生命体验之kevin-Y  阅读(823)  评论(0编辑  收藏  举报