如何在不重新编译VS2008中的解决方案的情况下热交换引用DLL?

时间:2011-05-18 22:55:43

标签: c# visual-studio-2008 reference

我们的解决方案提供了一个DLL,用于通过以太网与某些硬件进行通信。我们已经创建了第二个DLL,可以用来模拟硬件,这样我们的开发人员就不需要在每个办公桌上都有所说的硬件。

软件不应该知道它是使用真实硬件还是模拟器。如何在不需要重新编译解决方案的情况下交换引用?

我们可以只指定两个引用相同,只需注册/取消注册我们想要引用的正确的DLL吗?

[更新] 注意:第一个DLL是我们无法访问的第三方DLL。第二个DLL是我们用C ++创建的。我们的应用程序是用C#编写的。

4 个答案:

答案 0 :(得分:2)

使两个DLL实现一个通用接口(ICommunicateToYourHardware)并编写应用程序代码以通过反射而不是通过引用来发现DLL。

每次请求添加示例

此示例中的接口称为IAuthenticate,但您可以使用其中的任何接口。在这种情况下,我实际上正在寻找任何数量的IAuthenticate类。在您的情况下,如果不同的DLL放置在相同的相对路径中,则相同的编译将引入不同的DLL。

 // We need a container for the DLL files that we find and then a container for the instances of 
    // the plug ins created from the dlls. In this test we are only really looking for One such plug in
    // but I prefer to use collections for such things as it allows for a more scalable design. This technique
    // works for 1, 100, or more plugins and/or methods.
    private List<string> _DLLS;
    private List<iAuthenticate> _PlugIns;

    private int LoadPlugIns(string Path)
    {
        /// Within the designated Path (and in all subdirectories) locate all .dll files and put the path 
        /// to these files in a collection.
        GetDLLS(Path);
        foreach (string dirName in Directory.GetDirectories(Path))
        {
            LoadPlugIns(dirName);
        }

        // For each .dll file, inspect it (using reflection) to determine if it is of the iAuthenticate Type
        // if it is, create and instance of the object and store it in a collection, and assign a delegate to 
        // invoke its Authenticate method from the host application.
        foreach (string DLL in _DLLS)

        {
            Assembly myAssembly = Assembly.LoadFrom(DLL);
            Type[] Types = myAssembly.GetTypes();
            foreach (Type myType in Types)
            {
                Type T = myType.GetInterface("iAuthenticate");
               if (T != null)
                {
                    if (_PlugIns == null) { _PlugIns = new List<iAuthenticate>(); }
                    _PlugIns.Add((iAuthenticate)myAssembly.CreateInstance(myType.FullName));
                }
            }
            foreach (iAuthenticate iAuth in _PlugIns)
            {
                this.Authorize += iAuth.Authenticate;
            }
        }
        return _PlugIns.Count;
   }

    private void GetDLLS(string Path)
    {
        if (_DLLS == null){_DLLS = new List<string>();}
        foreach (string filename in Directory.GetFiles(Path, "*.dll")) 
        {
            _DLLS.Add(filename);
        }
    }

一旦我们通过反射获得了引用集,我们就可以调用它的方法:

    private void btnLogon_Click(object sender, EventArgs e)
    {
        try
        {
            if (Authorize.Invoke(txtUsername.Text, txtPassword.Text, txtPath.Text))
            {
                this.BackgroundImage = TelefloraDemo.Properties.Resources._189469;
                this.pnlLogon.Visible = false;
                MessageBox.Show("You have Logged On!");
            }
        }
        catch (AuthenticationException aex)
        {
            DemoCode.LogException(aex);
            MessageBox.Show(aex.ToString());
        }
        catch (Exception ex)
        {
            DemoCode.LogException(ex);
            MessageBox.Show("No Authenticator");
        }

    }

    public delegate bool Authenticate(string Username,string Password,string Path);
    public event Authenticate Authorize;

现在,显然你的里程可能会有所不同,但这应该会让你走上成功之路。 (是的,还有其他方式,我喜欢这个..)

答案 1 :(得分:2)

MEF(托管扩展性框架)使得执行此类操作变得非常容易。只需确保您的真实和模拟界面导出相同的合同并使用MEF组合来注入所需的版本。

这是simple example如何使用它。

答案 2 :(得分:0)

这来自MSDN

  

您可以重定向装配绑定   引用另一个版本的   通过使用中的条目进行汇编   应用程序或机器配置   文件。您可以将引用重定向到   .NET Framework程序集,第三方   装配件或您自己的装配件   应用。每个版本的.NET   Framework具有机器配置   文件和任何重定向信息   在该文件中影响所有应用程序   在该版本的.NET下运行   框架。

答案 3 :(得分:0)

引用两者并使用工厂类创建适当的接口。然后,您可以使用某种外部机制:配置文件,注册表项,计算机名称,构建标识符等...以使工厂发出正确的接口。