[英]Load dotnet project files in F# Interactive
I have a F# dotnet project with some dependencies in my .fsproj
(eg <PackageReference Include="FSharp.Data" Version="3.0.0-beta4" />
).我有一个 F# dotnet 项目,在我的.fsproj
有一些依赖.fsproj
(例如<PackageReference Include="FSharp.Data" Version="3.0.0-beta4" />
)。
Now I want to test some functions in a module I wrote, so I start fsharpi
and try to load my module with #load "Program.fs";;
现在我想测试我编写的模块中的一些功能,所以我启动fsharpi
并尝试使用#load "Program.fs";;
加载我的模块#load "Program.fs";;
. .
However, then I get error FS0039: The type 'CsvProvider' is not defined
.但是,然后我收到error FS0039: The type 'CsvProvider' is not defined
。
How can I load my module with the correct dependencies?如何使用正确的依赖项加载我的模块?
I have seen workarounds which include manually loading all required dll
s from some obscure system dependent path (eg #load a package in F# interactive (FSharpChart.fsx) ), but I guess there must be a better way to do this.我已经看到了一些解决方法,其中包括从一些模糊的系统相关路径(例如#load a package in F# interactive (FSharpChart.fsx) )手动加载所有必需的dll
,但我想必须有更好的方法来做到这一点。
In order to get access to the code in imported libraries, you need to tell the FSI to load them.为了访问导入库中的代码,您需要告诉 FSI 加载它们。
At the lowest level, this can be done with an #r
directive:在最低级别,这可以通过#r
指令完成:
#r "./packages/FSharp.Data/lib/whatever/FSharp.Data.dll"
This is often sufficient for one-off purposes.这通常足以满足一次性目的。
However, if there are a lot of references, your IDE can usually automate this for you.但是,如果有很多引用,您的 IDE 通常可以为您自动执行此操作。 For example, in Visual Studio, you can right-click the project and select either "Send References to F# Interactive" or "Generate Script File with References" (not sure about the exact wording).例如,在 Visual Studio 中,您可以右键单击项目并选择“将引用发送到 F# Interactive”或“生成带有引用的脚本文件”(不确定确切的措辞)。 The same options are available in VSCode if you have the Ionide extension installed.如果您安装了 Ionide 扩展,则 VSCode 中也有相同的选项。
Also, there is an active proposal+prototype for supporting packages in FSI directly - see https://github.com/fsharp/fslang-suggestions/issues/542 .此外,还有一个用于直接在 FSI 中支持包的活动提案+原型 - 参见https://github.com/fsharp/fslang-suggestions/issues/542 。 However, that is not yet merged and seems to have stalled a bit.然而,这还没有合并,似乎有点停滞不前。
There are a few option for doing this, none of them perfect.有几个选项可以做到这一点,但没有一个是完美的。
If you are using Ionide, then you can right click on a project in F# view and choose "Generate References for FSI".如果您使用的是 Ionide,那么您可以在 F# 视图中右键单击一个项目并选择“为 FSI 生成引用”。 This will create an F# script that loads all of the dependencies and project files for you.这将创建一个 F# 脚本,为您加载所有依赖项和项目文件。 Write your test code below this.在下面写你的测试代码。
The downsides of this approach:这种方法的缺点:
If you are using Paket, then you can generate "load scripts" for your project:如果您使用的是 Paket,那么您可以为您的项目生成“加载脚本”:
dotnet paket generate-load-scripts
This will generate F# scripts in ./paket/load
.这将在./paket/load
生成 F# 脚本。 There will be a load script for each dependency (and its transitive dependencies) and for each Paket "group".每个依赖项(及其传递依赖项)和每个包“组”都有一个加载脚本。
This can automatically sync with your paket.dependencies
if you add this line:如果添加以下行,这可以自动与您的paket.dependencies
同步:
generate_load_scripts: true
See: https://fsprojects.github.io/Paket/paket-generate-load-scripts.html参见: https : //fsprojects.github.io/Paket/paket-generate-load-scripts.html
The downsides of this approach:这种方法的缺点:
#load
you project files manually您必须手动#load
您的项目文件 New with .NET 5, you can write Nuget strings directly in your fsx
files. .NET 5 的新功能,您可以直接在fsx
文件中编写 Nuget 字符串。 This is a great feature for quick scripts!这是快速脚本的一个很棒的功能!
#r "nuget: FParsec"
// Package with a specific version
// #r "nuget: FParsec,1.1.1"
open FParsec
#load "./Types.fs"
// etc...
The downsides of this approach:这种方法的缺点:
#load
you project files manually您必须手动#load
您的项目文件In an ideal world, we would be able to do something like this:在理想的世界中,我们将能够做这样的事情:
#r "fsproj: ./my-proj.fsproj"
open FParsec
// etc...
There is an issue for this here: https://github.com/dotnet/fsharp/issues/8764这里有一个问题: https : //github.com/dotnet/fsharp/issues/8764
As requested in the comments on Fyodor's answer, here's a script that I've used in the past to generate the #r
and #load
directives required to load an .fsproj
in F# Interactive:正如在Fyodor的答案意见要求,这里就是我已经在过去用来生成一个脚本#r
和#load
来加载所需的指令.fsproj
在F#互动:
module References
#r "System.Xml"
#r "System.Xml.Linq"
open System
open System.IO
open System.Linq
open System.Xml.Linq
let inline isNotNull o = o |> isNull |> not
let private getProject path =
Directory.EnumerateFiles(path, "*.*proj") |> Seq.head |> XDocument.Load
let generateDlls path =
let projectFile = getProject path
let references =
projectFile.Descendants <| XName.Get("HintPath", "http://schemas.microsoft.com/developer/msbuild/2003")
|> Seq.filter (fun reference -> reference.Value.ToLower().EndsWith(".dll"))
|> Seq.filter (fun reference -> reference.Value.StartsWith("$") |> not)
|> Seq.map (fun reference -> reference.Value)
let projects =
projectFile.Descendants <| XName.Get("ProjectReference", "http://schemas.microsoft.com/developer/msbuild/2003")
|> Seq.map (fun reference -> reference.Elements(XName.Get("Name", "http://schemas.microsoft.com/developer/msbuild/2003")).SingleOrDefault())
|> Seq.filter (fun nameElement -> nameElement |> isNotNull)
|> Seq.map (fun nameElement -> nameElement.Value)
|> Seq.map (fun reference -> sprintf "../%s/bin/debug/%s.dll" reference reference)
references
|> Seq.append projects
|> Seq.iter (fun reference -> printfn "#r @\"%s\"" reference)
let generateFs path =
let projectFile = getProject path
projectFile.Descendants <| XName.Get("Compile", "http://schemas.microsoft.com/developer/msbuild/2003")
|> Seq.map (fun reference -> reference.Attribute("Include" |> XName.op_Implicit))
|> Seq.filter (fun reference -> reference |> isNotNull && reference.Value.ToLower().EndsWith("fs"))
|> Seq.filter (fun reference -> reference.Value.Equals("AssemblyInfo.fs", StringComparison.CurrentCultureIgnoreCase) |> not)
|> Seq.iter (fun reference -> printfn "#load @\"%s\"" reference.Value)
// Example Usage:
// #load @"GenerateReferences.fsx"
// References.generateDlls __SOURCE_DIRECTORY__
// References.generateFs __SOURCE_DIRECTORY__
I'm not sure this is completely perfect, for instance, I don't think it gets dependency-ordering right.我不确定这是否完全完美,例如,我认为它没有正确的依赖顺序。 However, it should be a reasonable starting point if you want to enhance it.但是,如果您想增强它,它应该是一个合理的起点。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.