【问题标题】:File not found when a DLL made in F# used from a non-F# application references Fsharp.Core v4.4.1.0当非 F# 应用程序使用 F# 制作的 DLL 引用 Fsharp.Core v4.4.1.0 时找不到文件
【发布时间】:2018-06-15 12:44:06
【问题描述】:

我的背景:我有一个正在 Visual Studio 2017 中开发的 DLL,它将从一个专有应用程序中加载——这是我以专有格式将数据导出到我正在构建的数据库中的唯一方法。专有应用程序提供了一个包含它们的数据结构等的 DLL,我已经能够将其添加为依赖项(但仅出于某种原因与 .NET Framework 4.6.x 一起使用,不适用于 4.7.x)。发布者的代码示例都是用 C# 编写的,但我可能更喜欢用 F# 编写我的插件,因为我沉迷于 Haskell 并且一直想学习一种 ML 方言。但是,我仍处于学习 C# 或 F# 的早期阶段。想想“经验丰富的基于 Linux 的程序员,他们对整个 Windows 生态系统只有最基本的了解。”

我的问题:我构建了这个 DLL,我从专有应用程序加载它,然后我收到一个报告以下错误的弹出窗口:

Exception Type:FileNotFoundException
Details: could not load file or assembly 'FSharp.Core,
Version=4.4.1.0, Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a' or one of its 
dependencies. The system cannot find the file specified.

这似乎与Brent Tranberg's StackOverflow 问题根本不同,他至少能够加载依赖项;事后他们只是向他抱怨。这里甚至没有加载依赖项。所以问题是(我认为)NuGet 包没有被全局安装,也没有被复制到构建输出中,因此专有应用程序不知道它。到目前为止,我在网上找到的唯一有用的东西是告诉我显然what I'm trying to do is an antipattern:F# 库显然只应该在 F# 应用程序中使用,这些应用程序可以定义它们绑定到的 F# Core 版本;它们不应该实际包含 F# Core 库本身。

一定在这里误解了一些东西,因为这对我来说听起来很疯狂。在 .NET 上,DLL 不仅仅是“我可以从我的 F# 应用程序调用的 F# 代码库”,它是一个核心互操作性构造,多种不同的语言可以使用它来相互通信。如何将这个 F# 依赖项包含在一个库中,该库 用于完全了解 F# 代码的应用程序?

我是否应该违反之前的指南部分并“假设 FSharp.Core 在 GAC 中”——如果是这样,我该怎么开始这样做? (我被警告说“VS2017 不会将 FSharp.Core 安装到 GAC”由同一来源。)或者,我的意思是,有没有一种很好的方法静态链接此代码,因为动态链接不起作用?有没有办法将 NuGet PackageReference 转换为 Reference 以便我可以添加 <Private>true</Private> 以便它包含在 DLL 文件夹中?我还有什么其他选择?

(我已经尝试过后者,它实际上并没有将所需的 DLL 复制到构建文件夹中。我也尝试将 Fsharp.Core DLL 直接添加为“依赖项”——仍然没有骰子。它 如果我每次构建时都复制它会起作用,但对于 Visual Studio 不可能遇到的更深层次的问题,这似乎是一种非常脆弱的方法。)

【问题讨论】:

  • .NET DLL 与 Windows DLL 不同。 .NET DLL 确实“只是一个代码库”。因此,您的 F# 库恰好正在使用其他库,因此该其他库也必须存在于您要使用库的任何位置。这与使用其他库没有什么不同。
  • @FyodorSoikin 感谢您的评论,我将“在 Windows 上”改写为“在 .NET 上”以澄清是的,事实上,我不是在谈论 Windows DLL,而是在谈论 .NET DLL。然而,我仍然被困在“似乎没有办法让 Visual Studio 2017 将此文件包含在其构建输出中,除非在构建完成后将其复制过来”,这是一个非常奇怪的问题,我非常很惊讶被卡住了。

标签: .net dll f# dependencies visual-studio-2017


【解决方案1】:

(警告:自我回答,解决方法)

更多的谷歌搜索最终导致a very tangential thread about NuGet being confused about the version of .NET Core,否则这将无济于事,除非主要开发人员之一(Kevin Ransom)说对FSharp.Core的引用被隐含包括,因为“不需要大多数人明确引用 FSharp.Core 的项目”。我想从 C# 中使用的 F# 库不是“大多数”,但如果这不被支持根本我很惊讶。然而,他对那些确实想要明确引用它的人提出了一个建议,这对我来说是解决这个问题的一种解决方法。

所以我的解决方法如下所示:

  • 关闭 Visual Studio 2017。
  • 在单独的文本编辑器中打开 <ProjectName>.fsproj
  • 在前面的<PropertyGroup> 添加Kevin Ransom 的建议<DisableImplicitFSharpCoreReference>true</DisableImplicitFSharpCoreReference>
  • 追踪到FSharp.Core.dll的相对路径;就我而言,它位于..\..\..\..\.nuget\packages\fsharp.core\4.2.3\lib\net45\FSharp.Core.dll
  • 将其作为ItemGroup 添加到项目中,并持有Private Reference(这与PropertyGroup 并行存在)。因此,该参考对我来说如下所示:

      <ItemGroup>
        <Reference Include="FSharp.Core">
          <HintPath>..\..\..\..\.nuget\packages\fsharp.core\4.2.3\lib\net45\FSharp.Core.dll</HintPath>
          <Private>true</Private>
        </Reference>
      </ItemGroup>
    

    我不需要删除 NuGet Core 添加的&lt;PackageReference&gt;

  • 保存该文件,在 Visual Studio 2017 中重新打开解决方案,然后重新构建。
  • 然后FSharp.Core.dll 神奇地出现在我的构建文件夹中,并带有我自己的.dll 文件。

如果这是一个糟糕的解决方法,请在 cmets 中告诉我!我对这一切真的很陌生,在“该死的 VS 已经把这个愚蠢的文件放在那个愚蠢的目录中!”的机智结束阶段!所以如果上述步骤有点绝望,那就是原因。

【讨论】:

  • 通常在 nuget 或 paket 中显式引用 Fsharp.Core 会将其包含在 packages 目录中,并将其复制到构建输出目录中。而且,(我没有用 dll 尝试过),你可以在 VS 的 Build settings 的 Other flags 部分中指定 --standalone 标志。这将在编译的程序集中包含 Fsharp.Core。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-14
相关资源
最近更新 更多