简体   繁体   English

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

[英]How can I hot swap referenced DLL's without recompiling the Solution in VS2008?

Our solution has a reference to a DLL which is used to communicate to some hardware over Ethernet. 我们的解决方案引用了一个DLL,用于通过以太网与某些硬件进行通信。 We have created a 2nd DLL which can be used to simulate the hardware, so that our developers do not need said hardware at each of their desks. 我们已经创建了第二个DLL,可用于模拟硬件,因此我们的开发人员不需要在每个桌面上都使用所述硬件。

The software should not know if it is using real hardware or the simulator. 软件不应该知道它是使用真实硬件还是模拟器。 How can we swap the references without needing to recompile the solution? 我们如何交换引用而无需重新编译解决方案?

Can we just name both references the same and simply register/unregister the correct DLL that we want to reference? 我们可以只指定两个引用相同,只需注册/取消注册我们想要引用的正确的DLL吗?

[Update] Note: The first DLL is a 3rd party DLL that we do not have access too. [更新]注意:第一个DLL是第三方DLL,我们也没有访问权限。 The 2nd DLL was created by us in C++. 第二个DLL是我们用C ++创建的。 Our application is written in C#. 我们的应用程序是用C#编写的。

Make both DLL's implement a common interface (ICommunicateToYourHardware) and code the application to discover the DLL via reflection rather than by reference. 使两个DLL实现一个通用接口(ICommunicateToYourHardware)并编写应用程序以通过反射而不是通过引用来发现DLL。

Per Request adding sample 每个请求添加样本

The interface in this example is called IAuthenticate, but you can use any interface in it's place. 此示例中的接口称为IAuthenticate,但您可以使用其中的任何接口。 In this case I am actually looking for any number of IAuthenticate classes. 在这种情况下,我实际上正在寻找任何数量的IAuthenticate类。 In your case if the different DLLs are placed in the same relative path the same compilation will pull in the different DLLs. 在您的情况下,如果不同的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);
        }
    }

once we have the reference set via reflection we can invoke its methods like this: 一旦我们通过反射获得了引用集,我们就可以像这样调用它的方法:

    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;

Now, obviously your mileage may vary, but this should get you on a successful track. 现在,显然你的里程可能会有所不同,但这应该会让你走上成功之路。 (Yes, there are other ways, I like this one..) (是的,还有其他方法,我喜欢这个..)

MEF (Managed Extensibility Framework) makes it really easy to do this sort of thing. MEF(托管扩展性框架)使得执行此类操作变得非常容易。 Just make sure your real and mock interfaces export the same contract and use MEF composition to have the desired version injected. 只需确保您的真实和模拟界面导出相同的合同并使用MEF组合来注入所需的版本。

here is a simple example of how to use it. 这是一个如何使用它的简单示例

This is from MSDN 这是来自MSDN

You can redirect an assembly binding reference to another version of an assembly by using entries in the application or machine configuration files. 您可以使用应用程序或计算机配置文件中的条目将程序集绑定引用重定向到程序集的另一个版本。 You can redirect references to .NET Framework assemblies, third-party assemblies, or assemblies of your own application. 您可以将引用重定向到.NET Framework程序集,第三方程序集或您自己的应用程序的程序集。 Each version of the .NET Framework has a machine configuration file, and any redirection information in that file affect all applications running under that version of the .NET Framework. 每个版本的.NET Framework都有一个计算机配置文件,该文件中的任何重定向信息都会影响在该.NET Framework版本下运行的所有应用程序。

Reference both and use a factory class to create the appropriate interfaces. 引用它们并使用工厂类来创建适当的接口。 You could then use some sort of external mechanism: config file, registry entry, machine name, build identifier, etc... to cause the factory to emit the correct interface. 然后,您可以使用某种外部机制:配置文件,注册表项,计算机名称,构建标识符等...以使工厂发出正确的接口。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何将vs2008 C ++ OpenCV dll构建为vs2008 C#? - How to build vs2008 c++ OpenCV dll to vs2008 C#? 如何获得vs2008的intellisense成员列表以显示完整签名? - How do I get vs2008's intellisense member list to show full signatures? 如何在VS2008中有选择地打开或关闭特定类别的Code Analysis构建警告? - How can I selectively turn on or off specific categories of Code Analysis build warnings in VS2008? 如何使用VS2008将应用程序清单嵌入到应用程序中? - How can I embed an application manifest into an application using VS2008? 如何在 VS2008 + .NET 3.5 下检查内容控件? - How can I check a Content Control under VS2008 + .NET 3.5? 如何获得VS2008 C#项目的测试覆盖率统计信息 - how can I get test coverage statistics for VS2008 C# project 如何在VS2008中找到可用的异常名称(在intellisense中) - How can I find exception names (in intellisense) availible to throw in VS2008 在VS2008中,对于C#,我如何确定需要哪些引用,哪些不需要? - IN VS2008, for C#, How can I figure out which references are needed and which are not? 如何以编程方式在vs 2008中创建新的空白解决方案? - How can I create new blank solution in vs 2008 programmatically? 如何在VS2008中更改智能感知设置? - How do i change the intellisense settings in VS2008?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM