【问题标题】:Anycpu nuget package the requires either 32 bit or 64 bit packageAnycpu nuget 包需要 32 位或 64 位包
【发布时间】:2015-04-18 15:35:01
【问题描述】:

我有一个(anycpu)nuget 包“my_shared_library”,它必须引用一个 32 位或 64 位的 nuget 包“non_anycpu_dependency”(它是数据库访问 dll)。

我希望 32 位和 64 位应用程序都能够使用“my_shared_library”。

如何让 32 位和 64 位程序都使用“my_shared_library”?

我在想我要么必须有 2 个版本的“my_shared_library”,或者在运行时有一些方法可以根据运行时位数选择正确的 32 位/64 位 nuget 包“non_anycpi_dependency” .

有人解决了这个问题吗?由于大多数数据库 dll 不是 anycpu,我认为这是一个常见问题。

提前致谢,

【问题讨论】:

    标签: .net nuget 32bit-64bit nuget-package


    【解决方案1】:

    有人解决了这个问题吗?

    是的,微软有。他们需要为他们的 SQL Server Compact 包解决同样的问题。它有一个托管程序集 System.Data.SqlServerCe.dll,充当托管程序的适配器,以及一堆实现实际数据库引擎的本机 DLL。我不推荐它们绑定到本机 DLL 入口点的方式,我会假设您使用 pinvoke。我建议你使用this technique 以确保客户端程序可以运行AnyCPU。

    重复那篇文章的本质,你想在初始化方法或静态构造函数的某个地方执行这段代码:

    public static void SetupDatabaseBinaries() {
        var path = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
        path = Path.Combine(path, IntPtr.Size == 8 ? "amd64" : "x86");
        bool ok = SetDllDirectory(path);
        if (!ok) throw new System.ComponentModel.Win32Exception();
    }
    
    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern bool SetDllDirectory(string path);
    

    唯一重要的步骤是让用户的项目将本机 DLL 复制到项目的 amd64/x86 目录中。这需要一个后期构建步骤,就像 Compact 包所做的那样。你需要下载 Nuget 包来看看他们是怎么做到的,这不是很简单。运行 VS 提升,创建一个虚拟控制台模式项目并检索 Sql Server Compact 的 Nuget 包。安装后,使用 Project + Properties,Build events 选项卡并注意它是如何添加此构建后事件的:

    if not exist "$(TargetDir)x86" md "$(TargetDir)x86"
    xcopy /s /y "$(SolutionDir)packages\Microsoft.SqlServer.Compact.4.0.8876.1\NativeBinaries\x86\*.*" "$(TargetDir)x86"
    if not exist "$(TargetDir)amd64" md "$(TargetDir)amd64"
    xcopy /s /y "$(SolutionDir)packages\Microsoft.SqlServer.Compact.4.0.8876.1\NativeBinaries\amd64\*.*" "$(TargetDir)amd64"
    

    没什么大不了的,除了创建 x86 和 amd64 子目录并将 DLL 复制到其中之外,它什么也不做。棘手的部分是让您的 Nuget 包添加此构建事件。查看包文件夹,了解实现此目的的魔法。您可能希望尽可能地遵循该示例以避免错误。查看 packages\Microsoft.SqlServer.Compact.4.0.8876.1\tools 目录,它包含两个执行此操作的 PowerShell 脚本文件。 Install.ps1 在安装结束时运行。创建后期构建步骤的函数在 VS.psm1, Add-PostBuildEvent 中。祝你好运。

    【讨论】:

    • 另请注意,有一个 AddDllDirectory() 作为 windows 7+ / server 2008+ 的 windows 更新提供,默认情况下包含在 windows 8 / server 2012 上。多个库有不同的负载要求。它还要求您调用 SetDefaultDllDirectories() 并带有一个标志,以指示将在每次库加载时搜索由添加/删除函数指定的路径。
    【解决方案2】:

    一旦您引用了针对特定位数的包,您就会陷入困境。您可能能够获得足够的间接编译,但最终会在运行时得到 BadImageFormatException

    您可以做的是创建一个 AnyCPU 程序集,其中包含与您拥有的特定程序集中的具体实现相匹配的接口。那么你所有的 AnyCPU 程序集都应该只引用接口。

    在要驱动应用程序的 EXE 中,您必须选择它是 64 位还是 32 位。在此 EXE 程序集中,您可以根据需要引用原始 32 或 64 位程序集(或 nuget 包)。

    要使用此解决方案,Autofac、StructureMap 或 Unity 等依赖注入框架将有助于减少管理为您的类提供具体实现的痛苦。

    【讨论】:

    • 感谢 Autofac 的参考,这看起来很有趣。
    猜你喜欢
    • 2011-12-07
    • 2018-02-21
    • 2012-06-12
    • 2015-05-30
    • 2012-10-26
    • 1970-01-01
    • 2011-08-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多