根据用户安装的软件使用正确版本的供应商DLL

时间:2014-11-05 23:32:21

标签: c# .net dll

尝试使用正确版本的供应商程序集,具体取决于用户计算机上安装的供应商软件版本。这个问题非常相似,但给出的建议似乎不起作用:

How to use two different Microsoft Interop assemblies in one project?

问题的关键在于我需要实例化特定版本的命名空间和类,具体取决于用户机器的情况。我不想将这两个组件用于各种目的;恰到好处。一些实际的代码,使用WordPerfect及其API,PerfectScript:

这是一个简单的设置,仅使用WPx4 dll

using WordPerfect;

namespace WP_PS_Tools {

public class WP_PerfectScript {
    public PerfectScript perfectScript { get; set; }
    public IntPtr _wpHandle { get; set; }

    /**
     * Initialize perfect script object
     */
    public WP_PerfectScript()
    {
        perfectScript = new PerfectScript();
    }
...

这里没问题。 " WordPerfect"参考是我从供应商" wpwin14.tlb"创建的主互操作程序集。

但是,我的一些用户安装了WPx6,因此他们需要使用较新的WPx6 dll。这些dll非常相似,具有几乎相同的方法,并且共享相同的类名,并且可以共享相同的命名空间(取决于我如何创建主Interop程序集)。

我首先尝试使用此问题所尝试的路由:Allowing multiple versions of the same COM library,Microsoft对如何修改程序集以包含2个版本进行了非常神秘且未完成的描述:How to: Wrap Multiple Versions of Type Libraries。我也无法弄清楚如何将另一个组件添加到现有组件中,而且我不相信这实际上会有所帮助。

下一个徒劳的尝试是尝试以某种方式抽象类,以便可以调用其中一个,具体取决于特定的安装:

using Corel.WordPerfect14;

namespace WP_PS_Tools {

public class WP14_PerfectScript {
    public virtual PerfectScript perfectScript { get; set; }
    public IntPtr _wpHandle { get; set; }

    /**
     * Initialize perfect script object
     */
    public WP14_PerfectScript()
    {
        perfectScript = new PerfectScript();
    } 
.
.
.

using Corel.WordPerfect16;

namespace WP_PS_Tools
{
public class WP16_PerfectScript: WP14_PerfectScript
{
    public PerfectScript perfectScript { get; set; }


    public WP16_PerfectScript()
    {
        perfectScript = new PerfectScript();
    }
}
}

由于主要问题,这甚至都没有编译:属性perfectScript必须被转换为PerfectScript类型的一个或其他版本(在此示例中,类Corel.WordPerfect14.PerfectScript或Corel.WordPerfect16.PerfectScript )。插入" new"按预期做了:我得到了一个完美运行的WPx4 dll版本(但无法与已经运行的WPx6程序进行交互)。据我所知,除了PerfectScript类本身之外没有其他更抽象的类型,所以我不能使用该类来继承。

我也尝试将两个程序集命名完全相同,但Visual Studio不允许我使用相同的名称引用它们。然后我尝试使用相同的名称创建程序集,然后重命名文件名。我被允许添加它们作为参考,但结果是其他问题提到的类名的模糊性。

接下来我尝试使用extern alias关键字,但结果却出现了相同的类型转换问题。

这个问题必须有一个简单的答案!如果"虚拟"那肯定会很好。在一个属性意味着你可以覆盖类型,但唉,事实并非如此。

我想我可能只需编译我的应用程序的两个版本,使用不同的引用,但该解决方案不太理想。

1 个答案:

答案 0 :(得分:2)

如果我理解正确,您希望通过计算机上安装的WordPerfect版本运行PerfectScript命令,但您不希望编译/安装/维护多个版本的软件。

我解决这个问题的方法是为我维护的软件实现一个插件系统。 “网络上有多种资源,对我来说有用的是 Factory Pattern的实现。

  1. 定义要运行脚本的抽象类接口。此类存在于您的应用程序中,不关心WordPerfect的不同版本。此类需要驻留在您自己的应用程序链接的DLL中,因为它将在您要创建的插件之间共享。

  2. 为您支持的每个WordPerfect版本实现抽象类。将每个实现放入自己的DLL中。因此,每个DLL仅涉及特定版本的WordPerfect。

  3. 使用System.Reflection.Assembly.Load(String)

  4. 在运行时加载客户机上安装的匹配WordPerfect的dll
  5. 遍历程序集中的类型,找到一个实现抽象类的类,获取该类型的ConstructorInfo并调用它。

  6. 这里的最终目标是使用.net的反射功能在运行时构造一个非常特定的类。您并不真正关心类的具体细节,只是它实现了您的抽象类,为它提供了一个通用接口,您可以使用您支持的WordPerfect版本。

    希望这有帮助!