Macos F#交互式、NuGet和外部库
我正在尝试在OS X El Capitan上的Xamarin Studio 5.9.8中运行suave(一个Web服务器)的演示代码Macos F#交互式、NuGet和外部库,macos,xamarin,f#,nuget,suave,Macos,Xamarin,F#,Nuget,Suave,我正在尝试在OS X El Capitan上的Xamarin Studio 5.9.8中运行suave(一个Web服务器)的演示代码 module ServerTest = open Suave // always open suave open Suave.Http.Successful // for OK-result open Suave.Web // for config startWebServe
module ServerTest =
open Suave // always open suave
open Suave.Http.Successful // for OK-result
open Suave.Web // for config
startWebServer defaultConfig (OK "Hello World!")
当我实际构建代码时,它会按预期工作。但是,当我尝试用ctrl+return以交互方式运行它时,我得到了一个错误
名称空间或模块“Suave”没有定义。我四处看了看,它看起来很像。有没有办法让它在OS X上工作?当您构建代码时,有关引用DLL的信息并不包含在代码本身中,而是包含在其他地方(项目文件)。
但当您在FSI中执行代码时,FSI看到的只是代码。它没有从中获取引用的项目文件
但是,由于FSI仍然需要偶尔加载引用的DLL(否则,它不会非常有用),因此它提供了一种在代码中对它们进行编码的方法。具体地说,就是#r
指令描述了这种方式
不幸的是,当您使用编译器构建代码时,这些指令不受支持。编译器在看到它们时将生成一个错误
因此,您似乎有一个选择:要么用FSI执行代码,要么用编译器构建代码。不能对两者使用相同的代码
幸运的是,有一些技巧可以解决这个问题
首先,您可以利用一个名为INTERACTIVE
的特殊条件编译变量,将#r
指令放入#if
中,这样只有FSI才会看到它,但编译器不会:
#if INTERACTIVE
#r "./path/to/my.dll"
#endif
其次,您可以创建一个单独的脚本文件来加载引用,然后加载实际的代码文件:
#r "./path/to/my.dll"
#load "./my_code.fs"
然后用FSI执行这个脚本文件
在这两种情况下,路径都是相对于脚本文件的。
这意味着您得到的“未找到”错误可能是由于到Suave DLL的路径不正确造成的。我严重怀疑DLL是否与代码文件位于同一目录中。而且它没有扩展。您尝试过使用相同的\r
指令吗?我没有。指令是否仅在*.fsx文件中工作?Xamarin甚至不允许我在模块内键入#r
。这些指令在*.fsx文件或FSI(无论您以何种方式与之交互)中工作,而FSI是执行*.fsx文件的东西,因此这应该是有意义的。链接到的页面适用于*.fsx和FSI,而不适用于Visual Studio。它只是碰巧使用VS作为演示工具。我试图在一个*.fs文件中实现这一点。我应该默认使用*.fsx文件吗?我添加了#if INTERACTIVE#r“Suave”#endif
在*.fs文件中,但现在我在/Library/Frameworks/Mono.framework/Versions/4.0.5/lib/Mono/4.5中找不到文件'Suave',我的路径是#r/。/packages/Suave.0.32.1/lib/net40/Suave.dll
,这在实践中似乎非常脆弱,取决于相关库的更新频率。这就是为什么不应该在脚本中执行任何非常复杂的操作。对于复杂的东西,构建代码并运行可执行文件。脚本最好保留用于经常更改的实验或轻量级任务,因此每次更改后重新生成脚本的成本相对较高。此外,如果您坚持将其作为脚本运行,则可能不应该使用旨在生成脚本的目录结构。把包放在特殊的地方,用版本和框架标记,所有这些都是为了方便构建。如果您的解决方案是基于脚本的,那么最好将引用放在脚本旁边。毕竟,*.exe文件就是这样工作的。我应该在哪里添加#if语句?如果我将其添加到.fsx文件中,我会得到错误FS0010:交互中意外的关键字“open”。在此点“;”或“;”之前应为不完整的结构化构造或者其他令牌。
只在.fsx中添加#r[path to dll]是可行的。。