Anycpu nuget包需要32位或64位的包



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

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

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

我在想,我要么必须有两个版本的"my_shared_brary",要么在运行时有某种方法可以根据运行时的比特数选择正确的"non_anycpi_dependency"的32bit/64bit nuget包。

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

提前感谢,

有人解决了这个问题吗?

是的,微软有。他们需要为他们的SQL Server Compact包解决完全相同的问题。它有一个托管程序集System.Data.SqlServerCe.dll,其作用类似于托管程序的适配器,还有一组实现实际数据库引擎的本机dll。它们绑定到本机DLL入口点的方式不是我推荐的,我将根据您使用pinvoke的假设进行工作。我建议您使用此技术来确保客户端程序可以运行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)packagesMicrosoft.SqlServer.Compact.4.0.8876.1NativeBinariesx86*.*" "$(TargetDir)x86"
if not exist "$(TargetDir)amd64" md "$(TargetDir)amd64"
xcopy /s /y "$(SolutionDir)packagesMicrosoft.SqlServer.Compact.4.0.8876.1NativeBinariesamd64*.*" "$(TargetDir)amd64"

除了创建x86和amd64子目录并将DLL复制到它们之外,它什么都没做。棘手的部分是让你的Nuget包添加这个构建事件。看看包文件夹中实现这一点的魔法。你可能想尽可能地按照这个例子来避免错误。查看packages\Microsoft.SqlServer.Compact.40.8876.1\tools目录,它包含两个执行此操作的PowerShell脚本文件。Install.ps1在安装结束时运行。创建生成后步骤的函数位于VS.psm1中的AddPostBuildEvent。祝你好运。

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

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

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

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

最新更新