我理解为什么在32位和64位版本中提供System.Data.SQLite.dll。所以我们不要再纠缠于此并继续前进。 :)
由于它以这种方式完成,它似乎使得纯粹的C#开发变得更加困难,有3个选择。
仅支持32位并强制管理 程序集编译x86并在32或64运行时处理 当你在64位时失去优势 环境。
是强制64位,只支持64位而丢失 能够以32位运行但获得64位的所有优势。
是创建两个版本的程序集 编译x86并使用32位SQLite和另一个编译x64的SQLite 并使用64位SQLite。它阻止使用“ANY”作为编译选项 并且能够轻松地将单个构建部署到任一类型。它的 从我们的发展角度来管理并不是那么可怕 将需要两个项目。只将C#代码正式合二为一, 另一个只使用“链接”到另一个代码。这个 仅用于编译目的。仍然让我们不得不 管理两个输出以进行部署。
尽管如此,我只是在寻找确认以上是唯一正确的选择。
如果我还有其他选择,请告诉我。特别是如果有一种方法可以获得一个可以编译为ANY的单个C#DLL,那么它可以利用32位或64位,具体取决于它的运行位置,仍然使用System.Data.SQLite.dll。
答案 0 :(得分:21)
这是对Springy76答案的详细阐述。这样做:
public class AssemblyResolver
{
public static void HandleUnresovledAssemblies()
{
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.AssemblyResolve += currentDomain_AssemblyResolve;
}
private static Assembly currentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
if (args.Name == "System.Data.SQLite")
{
var path = Path.Combine(pathToWhereYourNativeFolderLives, "Native");
if (IntPtr.Size == 8) // or for .NET4 use Environment.Is64BitProcess
{
path = Path.Combine(path, "64");
}
else
{
path = Path.Combine(path, "32");
}
path = Path.Combine(path, "System.Data.SQLite.DLL");
Assembly assembly = Assembly.LoadFrom(path);
return assembly;
}
return null;
}
}
确保生成的路径指向32位或64位SQLite Dll的正确位置。就个人而言,我对这个NuGet包中的结果有很好的结果:http://www.nuget.org/packages/SQLitex64
(你只需要使用NuGet包来获取已编译的SQLite Dll。一旦你得到它们,删除由NuGet和NuGet包本身创建的项目中对SQLite的引用。的确,留下引用在适当的位置可能会干扰此解决方案,因为SQLite永远不会被识别为未解析的程序集。)
尽可能早地调用'HandleUnresolvedAssemblies()',最好是在任何Bootstrapping期间。
答案 1 :(得分:14)
将主要应用程序保存在AnyCPU有两种常用的解决方案:
将x86和x64程序集安装到GAC中:它们可以(应该!)具有相同的程序集名称,GAC将自动决定是使用x86还是x64版本。
答案 2 :(得分:6)
Oracle的ODP.NET与原生32/64位OCI DLL存在类似的问题。
我们通过为项目创建'x86'和'x64'平台来解决它,然后手动编辑我们的项目文件以使用条件参考:
<Choose>
<When Condition="'$(Platform)' == 'x64'">
<ItemGroup>
<Reference Include="Oracle.DataAccess, processorArchitecture=x64">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\ThirdParty\ODP.NET\x64\Oracle.DataAccess.dll</HintPath>
</Reference>
<Content Include="..\ThirdParty\ODP.NET\x64\oci.dll">
<Link>oci.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="..\ThirdParty\ODP.NET\x64\orannzsbb11.dll">
<Link>orannzsbb11.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="..\ThirdParty\ODP.NET\x64\oraociei11.dll">
<Link>oraociei11.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="..\ThirdParty\ODP.NET\x64\OraOps11w.dll">
<Link>OraOps11w.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
</When>
<When Condition="'$(Platform)' == 'x86'">
<ItemGroup>
<Reference Include="Oracle.DataAccess, processorArchitecture=x86">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\ThirdParty\ODP.NET\x86\Oracle.DataAccess.dll</HintPath>
</Reference>
<Content Include="..\ThirdParty\ODP.NET\x86\oci.dll">
<Link>oci.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="..\ThirdParty\ODP.NET\x86\orannzsbb11.dll">
<Link>orannzsbb11.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="..\ThirdParty\ODP.NET\x86\oraociei11.dll">
<Link>oraociei11.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="..\ThirdParty\ODP.NET\x86\OraOps11w.dll">
<Link>OraOps11w.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
</When>
</Choose>
这使我们能够避免使用2个不同的项目。我相信你可以做类似的事情 SQLite的。
答案 3 :(得分:3)
从发展的角度来管理并不是那么可怕,因为我们需要两个项目。
这不是真的 - 您可以在同一个项目中使用两个构建配置。在部署时,您需要为x86和x64构建,但代码库和项目可以是相同的。
我目前在一个更大的生产项目中执行此操作,既包括SQLite,也包括其他包含x64和x86变体的本地/互操作库。
答案 4 :(得分:2)
除非您的应用需要超过4GB的内存,否则通常选择一种方式。请记住,64位操作系统上的32位应用程序具有64位的大部分优点,没有许多缺点。这就是为什么x86是VS 2010中.exe应用程序的默认目标。
答案 5 :(得分:2)
Branko Dimitrijevic说,“我确信你可以为SQLite做类似的事情。”这是正确的。 :)
遇到同样的问题,我找到了罗德尼的问题和布兰科的回答并亲自尝试过。对于任何想要查看我的SQLite实现的人,请转到:
<Choose>
<When Condition="'$(Platform)' == 'x64'">
<ItemGroup>
<Reference Include="System.Data.SQLite, Version=1.0.88.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>System.Data.SQLite\x64\System.Data.SQLite.dll</HintPath>
</Reference>
</ItemGroup>
</When>
<When Condition="'$(Platform)' == 'x86'">
<ItemGroup>
<Reference Include="System.Data.SQLite, Version=1.0.88.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>System.Data.SQLite\x86\System.Data.SQLite.dll</HintPath>
</Reference>
</ItemGroup>
</When>
</Choose>
<ItemGroup>
<Reference Include="Microsoft.CSharp" />
<Reference Include="System" />
<Reference Include="System.configuration" />
<Reference Include="System.Core" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
当然,您可以将HintPath命名为您喜欢的任何内容。
我发现这是一个完美的解决方案:我可以维护一个项目,并根据需要在目标平台之间快速切换。唯一可能的缺点是我无法在解决方案资源管理器中看到参考。但这是为整体功能付出的小代价。
答案 6 :(得分:1)
您还可以通过更改Visual Studio中的编译选项来解决此问题:
在Visual Studio中更改编译设置:
您的程序现在将始终以32位模式运行,即使在64位计算机上运行也是如此。
您还可以提供两个分发,一个针对上面提到的每个环境。虽然这将成为未来的标准,但对于我目前的项目来说,这是最好和最简单的选择。