c# - 在 .NET 中编译与版本无关的 DLL

标签 c# .net visual-studio-2008 dll version

场景

我有两个 Microsoft Office 包装器,一个用于 2003 年,一个用于 2007 年。由于同时运行两个版本的 Microsoft Office 是“官方不可能的”,Microsoft 也不推荐,所以我们有两个盒子,一个用于 Office 2003另一个使用 Office 2007。我们分别编译包装器。 DLL 包含在我们的解决方案中,每个框都有相同 结帐,但“卸载”了 Office 2003 或 2007,因此它不会尝试编译该特定 DLL。如果不这样做,将由于 Office COM DLL 不可用而引发编译错误。

我们使用 .NET 2.0 和 Visual Studio 2008。

事实

由于 Microsoft 在 2007 年神秘地更改了 Office 2003 API,重命名和更改了一些方法(叹气)从而使它们不向后兼容,我们需要这两个包装器。 我们在每台构建机器上都安装了解决方案并激活了一个 Office DLL。例如:带有 Office 2003 的机器卸载了“Office 2007”DLL,因此不编译它。另一个盒子是相同的想法,但相反。所有这一切都是因为我们不能在同一个盒子中有 2 个不同的 Office 用于编程目的。 (根据 Microsoft 的说法,从技术上讲,您可以将两个 Office 放在一起)但不是用于编程并且并非没有一些问题。

问题

当我们更改应用程序版本(例如从 1.5.0.1 到 1.5.0.2)时,我们需要重新编译 DLL 以匹配应用程序的新版本,这是自动完成的,因为 Office 包装器包含在解决方案中.由于包装器包含在解决方案中,因此它们继承了 APP 版本,但我们必须执行两次,然后将另一个 DLL“复制”到创建安装程序的机器上。 (痛苦……)

问题

是否有可能编译一个 DLL,它可以与应用程序的任何 版本一起工作,尽管是“旧的”?我读过一些关于 list 的内容,但我从来没有与这些进行过交互。任何指针将不胜感激。

这样做的 secret 原因是我们“多年以来”都没有更改我们的包装器,Microsoft 也没有使用他们古老的 API,但我们正在重新编译 DLL 以匹配 每个 上的应用程序版本释放我们做的。我想自动执行此过程,而不必依赖两台机器。

我无法从项目(两者都没有)中删除 DLL,因为存在依赖关系。

我可以创建第三个“主包装器”,但还没有考虑过。

有什么想法吗?还有其他人有同样的要求吗?

更新

澄清:

我有 1 个解决方案和 N 个项目。

“应用程序”+ Office11Wrapper.dll + Office12Wrapper.dll。

两个“包装器”都使用应用程序的依赖项 + 解决方案中的其他库(数据层、业务层、框架等)

每个包装器都有各自 Office 包(2003 和 2007)的引用。

如果我编译但没有安装 Office 12,我会收到 Office12Wrapper.dll 找不到 Office 2007 库的错误。 所以我有两台构建机器,一台装有 Office 2003,一台装有 Office 2007。在每台机器上进行完整的 SVN 更新 + 编译后,我们只需在“安装程序”中使用 office12.dll 来针对“相同”编译包装器代码,相同版本”。

注意:Office 2007 Build Machine 已“卸载”Office 2003 的包装程序,反之亦然。

提前致谢。

最佳答案

当 .NET 程序集解析器无法在运行时找到引用的程序集(在这种情况下,它无法找到应用程序所链接的特定包装器 DLL 版本),它的默认行为是失败并使应用程序崩溃。但是,可以通过 Hook AppDomain.AssemblyResolve 事件来覆盖此行为。只要找不到引用的程序集,就会触发此事件,它使您有机会用另一个程序集替换丢失的程序集(前提是它们兼容)。因此,例如,您可以替换您自己加载的包装器 DLL 的旧版本。

我发现最好的方法是在 Hook 事件的应用程序的主类上添加一个静态构造函数,例如:

using System.Reflection;

static Program()
{
    AppDomain.CurrentDomain.AssemblyResolve += delegate(object sender, ResolveEventArgs e)
    {
        AssemblyName requestedName = new AssemblyName(e.Name);

        if (requestedName.Name == "Office11Wrapper")
        {
            // Put code here to load whatever version of the assembly you actually have

            return Assembly.LoadFile("Office11Wrapper.DLL");
        }
        else
        {
            return null;
        }
    }
}

通过将它放在主应用程序类的静态构造函数中,可以保证它在任何代码尝试访问包装器 DLL 中的任何内容之前运行,确保钩子(Hook)提前到位。

您也可以使用策略文件进行版本重定向,但这往往更复杂。

关于c# - 在 .NET 中编译与版本无关的 DLL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/277817/

相关文章:

C# 线程 - 父访问问题

c# SELECT 与 FOR JSON

java - 错误请求 - 来自 Android 模拟器的 SOAP WCF Web 服务的主机名异常无效

c# - 如何缓存一行而不引发 "Row provided already belongs to a DataGridView"错误?

c# - 如何获取 Visual Studio 2008 编辑器窗口的左上角屏幕位置?

javascript - VS2008 脚本中的 ASP.NET MVC 标记有 "expected expression"警告

c# - WPF 性能与文本

c# - 为什么我的 var 调用不返回 DataListItems

.net - 是否有与 Excel 中的 NETWORKDAYS 等效的 .NET 方法?

c++ - 当我使用可变参数时,它适用于 int 和 double,但是当涉及到 float 时,就会出错