我试图解释有关传递依赖性的Release和Debug配置之间奇怪的F#编译器行为.我将Newtonsoft.Json在这里使用package作为基本依赖,因为这是我设法找到问题的最远,并且它使示例有点不那么抽象.
让我们创建一个名为的文库项目SerializerProject,Newtonsoft.Json通过paket 引用.在这个项目中只有一个模块:
module Serializer =
open System.IO
open System.Text
open Newtonsoft.Json
type OptionConverter() =
inherit JsonConverter()
(* only the signature is important, the implementation
and other methods are not interesting *)
override x.WriteJson(writer: JsonWriter, value: obj, serializer: JsonSerializer) =
(* ... *)
let fromJson<'a> (bytes: byte []): 'a =
let s = Encoding.UTF8.GetString(bytes)
use sr = new StringReader(s)
use jr = new JsonTextReader(sr)
let serializer = JsonSerializer()
serializer.Converters.Add(OptionConverter())
serializer.Deserialize<'a>(jr)
Run Code Online (Sandbox Code Playgroud)
现在让我们SerializerProject通过项目参考在同一个解决方案和参考中创建第二个项目.我想fromJson在我的新项目中使用,这就是我SerializerProject首先引用的原因.
module MyModule =
open Serializer
(* This is here just so we reference the fromJson function *)
let deserializer bytes = fromJson bytes
Run Code Online (Sandbox Code Playgroud)
这是重现行为的最小示例.
现在,当我在Debug配置中构建解决方案时,一切都编译并正常工作.但是当我切换到Release时,编译在第二个项目中失败,在deserializer定义中的MyModule中.确切的错误消息是这样的:
通过'Newtonsoft.Json.JsonWriter'引用的类型在未引用的程序集中定义.您必须添加对程序集'Newtonsoft.Json'的引用
我正在使用Visual Studio 2015 Update 3,F#工具(fsc,fsi)显示版本14.0.23413.0.
这有点意义,因为它正在读取元数据,SerializerProject并发现公共OptionConverter类型泄漏了JsonWriter它的公共WriteJson方法的类型(以及其他类型和其他方法,但首先遇到这个),但是让我想知道的是为什么这个在调试模式下工作,这只是发布模式中的一个问题.
Newtonsoft.Json传递到第二个项目时,为什么这不是Debug构建中的问题?正如评论中所建议的那样,我尝试Newtonsoft.Json使用ILSpy 引用和反编译第二个程序集,以查看编译器优化启用的内联是否应该归咎于此,但即使在Release配置中,第二个程序集如下所示:
call !!0 [SerializerProject]Serializer::fromJson<!a>(uint8[])
Run Code Online (Sandbox Code Playgroud)
该fromJson函数尚未内联JsonWriter直接公开类型,因此似乎有更微妙的事情发生.
这不是阻塞问题,我只是将转换器类型设为私有,因为我不想从外部使用它们,但我想深入挖掘F#编译器内部工作.
| 归档时间: |
|
| 查看次数: |
106 次 |
| 最近记录: |