使用反射在运行时加载程序集的问题

时间:2011-05-09 04:40:56

标签: c# reflection

我正在使用带有C#的VS2008来开发我的应用程序。在我的应用程序中有一个scenarion我必须在运行时加载点网组件因此我使用assembly.loadfrom(“程序集名称”)来加载程序集。现在的情况是: 在我的应用程序中,有一个下拉列表有两个选项。当用户选择option1并单击“Go”按钮时,assemblya将加载。同样,如果用户选择option2并点击“GO”按钮,将加载assembly2。两个程序集都具有相同的名称,但位置和版本不同。

问题: 当我选择option1时,assembly1被加载并且我可以成功调用方法,但是当我选择了option2程序集被加载但是在调用方法时我得到错误,因为没有加载该方法。 问题isny选项我选择第一个正常工作,第二个选项有调用方法的问题。

我的发现:  我发现如果我使用loadfrom选项加载程序集并再次使用相同的选项来加载另一个程序集,它将返回相同的上下文,因此该函数返回已加载到内存中的程序集。因此我们应该使用LoadFile而不是Loadfrom。我已经将loadfrom更改为loadfile但是我仍然得到相同的行为。

2 个答案:

答案 0 :(得分:1)

我刚刚进行了简单的测试:

我用代码创建了两个asseblies:
首先(称为test1.dll

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Test1
{
  public class Class1
  {
    public void SayHello()
    {
       System.Windows.Forms.MessageBox.Show("Test!");
    }
  }
}

第二次集会(也称为test1.dll):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Test1
{
  public class Class1
  {
    public void SayHello()
    {
       System.Windows.Forms.MessageBox.Show("Im a new Test!");
    }
  }
}

来电应用程序(带两个按钮的表单):

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Asseblies
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private System.Reflection.Assembly _assembly1 = null;
        private System.Reflection.Assembly _assembly2 = null;

        private void button1_Click(object sender, EventArgs e)
        {
            if (System.Object.Equals(_assembly1,null))
            {
                _assembly1 = System.Reflection.Assembly.LoadFrom(@".\test1\test1.dll");
            }

            object inst = _assembly1.CreateInstance("Test1.Class1");

            inst.GetType().InvokeMember("SayHello", System.Reflection.BindingFlags.InvokeMethod, null, inst, null);

        }

        private void button2_Click(object sender, EventArgs e)
        {
            if (System.Object.Equals(_assembly2, null))
            {
                _assembly2 = System.Reflection.Assembly.LoadFrom(@".\test2\test1.dll");
            }

            object inst = _assembly2.CreateInstance("Test1.Class1");

            inst.GetType().InvokeMember("SayHello", System.Reflection.BindingFlags.InvokeMethod, null, inst, null);
        }
    }
}

之后,按照以下方式放置了程序集和调用者应用程序:

AppDir
|
 - CallerApp.exe
|
 - test1
|  |
|   - test1.dll  <-- my first assembly
|
 - test2
   |
    - test1.dll  <-- my second assembly

在测试过程中我没有错误,我打电话的方法给了我适当的结果。您可能正在使用与我不同的实例创建/方法调用技术吗?

我相信你的问题属于绑定上下文,你调用方法或创建实例的方式。有一篇关于绑定上下文的好文章 - http://blogs.msdn.com/b/suzcook/archive/2003/05/29/57143.aspx它可以帮助你。

答案 1 :(得分:0)

尝试使用Assembly.Load并指定程序集的强名称。

Assembly library = Assembly.Load("library, Version=2.0.0.0, Culture=Neutral, PublicKeyToken=9b184fc90fb9648d");