Anycpu nuget包需要32位或64位包

时间:2015-02-17 19:53:13

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

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

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

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

我以为我要么必须有2个版本的" my_shared_library"或者也许在运行时有一些方法来选择正确的32位/ 64位nuget包" non_anycpi_dependency"基于运行时bit-ness。

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

提前致谢,

2 个答案:

答案 0 :(得分:9)

  

有没有人解决过这个问题?

是的,微软有。他们需要为他们的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选项卡,并注意它是如何添加此post build事件的:

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中。祝你好运。

答案 1 :(得分:1)

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

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

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

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