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



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

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

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

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

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

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

您可以使用相对路径并将示例复制到您的库中,但这不是很优雅。我们实际上在f#数据工具箱中有完全相同的问题,这是一个在封面下使用JsonProvider的库。

f# Data有一个特殊的选项。您可以在编译DLL时将示例作为资源嵌入-这样,类型提供程序将首先查找嵌入的资源(在您分发库之后工作),如果它不在那里,它将查找本地文件(在编译库时需要)。

看看f#数据工具箱是怎么做的:

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

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

<EmbeddedResource Include="json/bearer_token.json">
  <Link>json/bearer_token.json</Link>
</EmbeddedResource>
我相信JSON和XML提供程序都支持这一点。

最新更新