如果可以选择,混合模式程序集与单独的互操作 DLL 相比有何优缺点?

2024-01-23

当第 3 方组件以“混合模式程序集”和“单独的互操作 DLL”版本提供时,各自的优缺点是什么?

一个很好的例子是系统.数据.SQLite https://system.data.sqlite.org/index.html/doc/trunk/www/downloads.wiki.

上面的链接有这样一句话:

[混合模式程序集] 包仅应在由于某种原因必须将程序集二进制文件部署到全局程序集缓存的情况下使用。

但为什么?混合模式程序集似乎在我的项目中工作得很好,无需安装 GAC(只需 xcopy 到应用程序的 exe 目录)。少一个 DLL 真是太好了。它feels更整洁。那么有什么缺点呢?

反之亦然,为什么人们会/应该偏爱双 DLL“native-dll + interop-dll”版本呢?


免责声明:要获得明确的答案,您必须询问开发团队的人员,但这是我的最佳猜测。

在标准配置中,托管程序集将尝试查找并加载它所需的本机 DLL。它将在依赖于平台的目录中搜索(x86 or x64)。然后,它将加载在那里找到的 DLL,并继续向其抛出 P/Invoke 互操作。

这是与 .NET 中的本机库互操作的相当标准的过程 - 唯一的customSystem.Data.SQLite 代码是尝试定位 DLL 并加载正确版本的代码。其余的就是简单的 P/Invoke。但即便如此,当你与图书馆打交道时,这也是常见的做法。

The major这种方法的优点是库用户可以为AnyCPU平台,并且处理器架构将在运行时解析 - 如果您在 x86 或 x64 上运行,一切都会按预期工作,前提是两个本机 DLL 都可用。而且库作者得到的支持请求也更少。


让我们将其与混合模式方法进行比较。混合模式 DLL 有一些缺点,其中最主要的是它must特定于平台。因此,如果您选择这种方法,则必须将您的应用程序绑定到特定平台。如果您想同时支持 x86 和 x64,则必须构建单独的版本,每个版本都链接到正确版本的 System.Data.SQLite。

如果你没有完全正确地理解这一点,那么boom。更糟糕的是,如果你构建它是为了AnyCPUx64 开发机器上的平台,它将seem乍一看工作正常,但它会在客户的旧 x86 机器上崩溃。必须处理此类问题并不好,使用单独的 DLL 的简单解决方案可以完全解决该问题。

我能想到的另一个缺点是无法从内存加载程序集,但这最多只是一个小小的不便,因为这也适用于本机 DLL。

至于 GAC,我的猜测是,在单独的本机程序集的情况下,搜索它们的代码在某些情况下可能无法找到它们,或者可能会找到不同版本的 DLL。 System.Data.SQLite 中的代码非常努力地尝试定位本机 DLL,但混合模式 DLL 首先就不存在这样的问题,因此失败不是一种选择。


尽管如此,你还是说:

It feels tidier.

让我们仔细看看这一点。 :)

System.Data.SQLite 有相当多的unusual混合模式互操作方法。通常,您会使用 C++/CLI 来构建混合模式程序集。这使您可以将托管代码和本机代码结合起来sameC++/CLI 项目到单个 DLL 中并使用所谓的C++ 互操作 https://msdn.microsoft.com/en-us/library/ky8kkddw.aspx处理从托管/非托管屏障的一侧到另一侧的调用。这样做的优点是它比 P/Invoke 更轻、更快,因为它可以避免大部分编组。

System.Data.SQLite 做了一些不同的事情:它将其 C# 代码构建成网络模块, 进而使用 C++ 链接器 https://msdn.microsoft.com/en-us/library/k669k83h.aspx链接网络模块与本机 SQLite 代码。这会产生混合模式装配。

有趣的是,unline C++/CLI,C# 没有direct在同一混合模式程序集中调用本机代码的机制,因为 C# 最初并不打算在混合模式程序集中使用。因此,最终程序集中的 C# 代码将简单地P/调用自身。是的,你没有看错。这仍然感觉整洁吗?尽管如此,这是一个聪明的技巧。 :)

看一下中的代码UnsafeNativeMethods.cs:

#if PLATFORM_COMPACTFRAMEWORK
    //
    // NOTE: On the .NET Compact Framework, the native interop assembly must
    //       be used because it provides several workarounds to .NET Compact
    //       Framework limitations important for proper operation of the core
    //       System.Data.SQLite functionality (e.g. being able to bind
    //       parameters and handle column values of types Int64 and Double).
    //
    internal const string SQLITE_DLL = "SQLite.Interop.099.dll";
#elif SQLITE_STANDARD
    //
    // NOTE: Otherwise, if the standard SQLite library is enabled, use it.
    //
    internal const string SQLITE_DLL = "sqlite3";
#elif USE_INTEROP_DLL
      //
    // NOTE: Otherwise, if the native SQLite interop assembly is enabled,
    //       use it.
    //
    internal const string SQLITE_DLL = "SQLite.Interop.dll";
#else
    //
    // NOTE: Finally, assume that the mixed-mode assembly is being used.
    //
    internal const string SQLITE_DLL = "System.Data.SQLite.dll";
#endif

如果您想了解构建过程,请查看 C++ MSBuild 项目。以下是一些链接器选项,显示了网络模块的使用(在<AdditionalDependencies>):

<Link>
  <AdditionalOptions>$(INTEROP_ASSEMBLY_RESOURCES) %(AdditionalOptions)</AdditionalOptions>
  <AdditionalLibraryDirectories>$(INTEROP_LIBRARY_DIRECTORIES)</AdditionalLibraryDirectories>
  <AdditionalDependencies>$(ProjectDir)..\bin\$(ConfigurationYear)\$(Configuration)Module\bin\System.Data.SQLite.netmodule $(INTEROP_LIBRARY_DEPENDENCIES);%(AdditionalDependencies)</AdditionalDependencies>
  <Version>$(INTEROP_LINKER_VERSION)</Version>
  <GenerateDebugInformation>true</GenerateDebugInformation>
  <GenerateMapFile>true</GenerateMapFile>
  <MapExports>true</MapExports>
  <SubSystem>Windows</SubSystem>
  <OptimizeReferences>true</OptimizeReferences>
  <EnableCOMDATFolding>true</EnableCOMDATFolding>
  <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
  <TargetMachine>MachineX64</TargetMachine>
  <CLRUnmanagedCodeCheck>true</CLRUnmanagedCodeCheck>
  <KeyFile>$(INTEROP_KEY_FILE)</KeyFile>
  <DelaySign>true</DelaySign>
</Link>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如果可以选择,混合模式程序集与单独的互操作 DLL 相比有何优缺点? 的相关文章

  • 检测 Windows 重新启动是否是由于 Windows 更新造成的

    我的电脑上的一些应用程序一直在检测 Windows 更新是否重新启动 这是可以观察到的 因为它们会在 Windows 更新自动重启后重新启动 这非常有帮助 因为这些应用程序会重新加载更改 甚至unsaved更改或恢复选项卡 如果是浏览器 执
  • 来自其他位置的 .NET 参考 dll

    我正在根据第三方程序中包含的一些 DLL 制作一个程序 我不被允许自己分发这些 DLL 必须安装第三方程序才能使我的程序运行 我怎样才能引用这些DLL 我通过程序设置的注册表项知道它们的确切位置 我尝试在 Project gt Refere
  • 内部框架与新的 C# 技术

    如果我们开发了自己的 ORM 框架 并且该框架多年来运行良好 那么我们为什么要学习和使用全新的 net 技术 例如LINQ or Entity Framework or NHibernate or CSLA NET对于我们即将进行的软件项目
  • 如何使用 .schema 文件在 sqlite3 中创建 DB 文件

    我们的客户向我们提供了一个名为db schema 现在有一个命令可以用来运行这个文件来创建一个 dbsqlite3 中的文件 我可以做到这一点而不必输入中提到的所有查询吗db schema file 请帮忙 谢谢 如果该文件仅包含格式正确的
  • 如何在 C# 中将 excel ListObject 添加到给定工作表?

    我目前正在 C 中开发一个 Excel 插件 其中包含多种方法 表值函数 可供 Excel 用户和程序员 VBA 使用 如何编写一个方法 将新的 ListObject Excel 表 添加到给定的 Excel 工作表 并将给定的 DataT
  • SQL Server 2008 中 CLR 中的线程

    我有一个CLR运行在下面的进程SQL Server2008 它构建了多个表数据的缓存以保存在静态类中以供其他调用稍后使用 我的问题是 我可以通过生成线程来加载缓存中的每个数据集 表来改进加载此缓存的过程吗 我过去一直回避这一点 因为各种帖子
  • AutoCompleteTextView sqlite填充异常

    我的第一篇文章只有不到一半的文字 因此是第二篇 完整的 文章 我正在开发一个测试应用程序 使用 sqlite 填充两个 AutoCompleteTextView 我正在使用汽车制造商和模型进行测试 自动完成的 使自动完成 模型自动完成 ma
  • 服务器端生成的 Excel 中出现 System.Runtime.InteropServices.COMException 错误

    我们有一个 Web 应用程序 可以生成 Excel 电子表格并在服务器端运行宏 然后它通过电子邮件将它们发送给不同的人 它是传统报告风格的一部分 我们正在对其进行转换 但仍然支持我们作为 IIS 中的网站提供的新应用程序 我知道进行 Off
  • C#.NET VS2010 断点不起作用

    当我去调试代码时 所有断点都被透明填充 只留下轮廓 并且中间有一个感叹号的小三角形位于断点的角落 当我将鼠标悬停在断点上时 错误是 当前不会命中断点 源代码与原始版本不同 我在一个多小时内没有尝试调试我的代码 在此期间我添加了一个具有多个线
  • 在 WPF 中设置控件内容比将类绑定到选择器控件更好的方法是什么?

    我有一个分为 4 个面板的应用程序 有一个主绘图区域 一个顶部面板 一个左侧菜单面板和一个右侧子菜单面板 如下图所示 子菜单的内容由选择哪个顶部菜单按钮决定 子菜单的内容由选择哪个右侧菜单决定 例如 这是单击 网络设计和测试 扩展器上的第一
  • WatiN pressTab 不按 Tab

    有没有人找到了在 Internet Explorer 中使用 watiN 按 Tab 键的方法 您的意思是要按 Tab 键本身 还是只是单击看起来像 Tab 的 HTML 元素 对于后者 请对适当的元素 Div Span 等 使用 Clic
  • 复制到其他计算机时无法在 WcfTestClient 中添加服务

    我想在另一台计算机上运行 WcfTestClient VS2012 中包含的一个 而不安装 VS2012 这可能吗 在我已经安装了 NET 4 5 的机器上 但是当我尝试添加 Web 服务时 它给了我以下堆栈跟踪 Exception Tex
  • 使用 C# 在 Powerpoint 2013 中创建具有多个系列的图表

    我使用的是 VS2013 Ultimate 带有 Office 2013 已安装 PowerPoint Excel 和 Word 我正在用 C 编码 我正在使用 C 创建 PowerPoint 演示文稿 到目前为止 我已经成功地完成了我想做
  • 无法从 ComboBox 获取值

    我有一个简单的组合框 其中包含一些值 文本项 我使用 ComboBox DisplayMember 和 ComboBox ValueMember 来正确设置值 文本 当我尝试获取该值时 它返回一个空字符串 这是我的代码 表单加载事件 cbP
  • 带有 Firebird 的 .NET 实体框架:UTF-8 数据库出现错误“超出实现限制。块大小超出实现限制”

    我将 Firebird ADO NET 提供程序版本 5 5 与实体框架 5 结合使用 对于 Firebird UTF 8 数据库 带有投影的 LINQ to SQL 查询 包括有条件地将字符串属性设置为常量 会导致错误 超出实现限制 块
  • 如何在 Visual Studio 2015 中为多个解决方案和项目设置单个 Nuget 包文件夹

    我们正在 Visual Studio 2015 中开发多个解决方案 这些解决方案共享一些需要 nuget 包的核心项目 当从一个解决方案添加 nuget 包并随后由另一解决方案打开时 无法解析 nuget 引用 文件夹结构如下 Codeba
  • 将 SQLite 的 FTS3/4 与 Python 3 结合使用

    我一直在使用 python 的 Flask 框架开发 peewee 的示例博客应用程序 看https github com coleifer peewee https github com coleifer peewee 内部示例 gt 博
  • Visual Studio 2013 未发现单元测试

    我在 Visual Studio 2013 中有一个简单的解决方案 它由一个 Web 项目 一个库项目和一个单元测试项目组成 当我打开解决方案并尝试运行单元测试时 Visual Studio 不会发现它们 要运行测试 我尝试转到菜单并选择
  • ClickOnce 应用程序和 Windows 8 认证

    是否有可能有一个单击一次 http en wikipedia org wiki ClickOnce WPF http en wikipedia org wiki Windows Presentation Foundation应用程序经过认证
  • 在 Android 中使用 SQL (JDBC) 数据库

    在旧的 Java 应用程序中 我使用以下代码连接到 SQL 数据库并将其用于某些查询 private Connection dbConnection null System setProperty derby system home C C

随机推荐