来自f# XmlProvider的类型检查错误FS3033

时间:2022-05-22 15:49:20

I've been using the XmlProvider from FSharp.Data to generate types corresponding to a fragment of XML which I am storing in a file in the source directory of the F# project being built.

我一直在使用来自FSharp的XmlProvider。生成与我正在构建的f#项目源目录中存储的XML片段对应的类型的数据。

I parameterize the XmlProvider with the path of the file. This code is then compiled into a DLL.

我用文件的路径参数化XmlProvider。然后将该代码编译成一个DLL。

If I then reference the compiled DLL of this assembly from another F# project which is unable to read from the source directory then, at compile time for that project I get the error FS3033 'Cannot read sample XML from 'config_schema.xml': Could not find (path)'.

如果我接着从另一个无法从源目录读取的f#项目引用这个程序集的编译DLL,那么在该项目的编译时,我将得到错误FS3033 '无法从'config_schema '读取示例XML。xml':找不到(路径)'。

Why is this? My understanding was that after compilation, the type corresponding to the XML sample was a standard fully fledged type and this is what should end up in the compiled DLL. Why does a consumer of the type (code in the second project) still need to reference the sample to compile?

这是为什么呢?我的理解是,在编译之后,与XML示例对应的类型是标准的完全成熟的类型,这就是编译后的DLL中的结果。为什么类型的使用者(第二个项目中的代码)仍然需要引用示例进行编译?

1 个解决方案

#1


7  

This is subtle. When you compile code that uses a erasing type provider like XmlProvider or JsonProvider into a DLL, the compiler does not actually store the generated types. This means that when you reference the DLL from another library, the compiler will trigger the type provider again - even though the end-user code (user of your library) is not actually using the type provider.

这是微妙的。当您将使用擦除类型提供程序(如XmlProvider或JsonProvider)的代码编译到DLL中时,编译器实际上并不存储生成的类型。这意味着当您从另一个库引用DLL时,编译器将再次触发类型提供程序—即使最终用户代码(您的库的用户)实际上没有使用类型提供程序。

This means that the type provider needs to be able to access the sample, even after you compiled the library and distributed it to your users.

这意味着类型提供程序需要能够访问示例,即使您编译了库并将其分发给用户之后也是如此。

You could use relative paths and copy the samples with your library, but that's not very elegant. We actually have exactly the same problem in F# Data Toolbox which is a library that uses JsonProvider under the cover.

您可以使用相对路径并将示例复制到库中,但这不是很好。在f# Data工具箱中,我们实际上遇到了相同的问题,它是一个在封面下使用JsonProvider的库。

F# Data has a special option for this purpose. You can embed the sample as a resource when compiling the DLL - that way, the type provider will first look for an embedded resource (which works after you distributed your library) and if it's not there, it will look for a local file (which you need when compiling the library).

f#数据为此有一个特殊的选项。可以嵌入示例作为一个资源编译DLL时,提供者会首先寻找一个嵌入式资源类型(工作后你分布式库),如果它不是,它会寻找一个本地文件(你需要当编译库)。

See how this is done in F# Data Toolbox here:

看看如何在f#数据工具箱中完成:

type Response = JsonProvider<"json/bearer_token.json", 
  EmbeddedResource="FSharp.Data.Toolbox.Twitter,bearer_token.json">

The embedded resource is set in the project file:

在项目文件中设置嵌入式资源:

<EmbeddedResource Include="json/bearer_token.json">
  <Link>json/bearer_token.json</Link>
</EmbeddedResource>

I believe this is supported for both JSON and XML providers.

我认为JSON和XML提供程序都支持这一点。

#1


7  

This is subtle. When you compile code that uses a erasing type provider like XmlProvider or JsonProvider into a DLL, the compiler does not actually store the generated types. This means that when you reference the DLL from another library, the compiler will trigger the type provider again - even though the end-user code (user of your library) is not actually using the type provider.

这是微妙的。当您将使用擦除类型提供程序(如XmlProvider或JsonProvider)的代码编译到DLL中时,编译器实际上并不存储生成的类型。这意味着当您从另一个库引用DLL时,编译器将再次触发类型提供程序—即使最终用户代码(您的库的用户)实际上没有使用类型提供程序。

This means that the type provider needs to be able to access the sample, even after you compiled the library and distributed it to your users.

这意味着类型提供程序需要能够访问示例,即使您编译了库并将其分发给用户之后也是如此。

You could use relative paths and copy the samples with your library, but that's not very elegant. We actually have exactly the same problem in F# Data Toolbox which is a library that uses JsonProvider under the cover.

您可以使用相对路径并将示例复制到库中,但这不是很好。在f# Data工具箱中,我们实际上遇到了相同的问题,它是一个在封面下使用JsonProvider的库。

F# Data has a special option for this purpose. You can embed the sample as a resource when compiling the DLL - that way, the type provider will first look for an embedded resource (which works after you distributed your library) and if it's not there, it will look for a local file (which you need when compiling the library).

f#数据为此有一个特殊的选项。可以嵌入示例作为一个资源编译DLL时,提供者会首先寻找一个嵌入式资源类型(工作后你分布式库),如果它不是,它会寻找一个本地文件(你需要当编译库)。

See how this is done in F# Data Toolbox here:

看看如何在f#数据工具箱中完成:

type Response = JsonProvider<"json/bearer_token.json", 
  EmbeddedResource="FSharp.Data.Toolbox.Twitter,bearer_token.json">

The embedded resource is set in the project file:

在项目文件中设置嵌入式资源:

<EmbeddedResource Include="json/bearer_token.json">
  <Link>json/bearer_token.json</Link>
</EmbeddedResource>

I believe this is supported for both JSON and XML providers.

我认为JSON和XML提供程序都支持这一点。