我们有一个F#程序集(AssemblyOne
),该程序集在单个Visual Studio 2012解决方案中引用了另一个F#程序集(AssemblyTwo
)。 AssemblyTwo
引用了C#DLL(MyCSharpLib
)。AssemblyOne
中定义的函数调用AssemblyTwo
中定义的函数:
namespace AssemblyOne
[<RequireQualifiedAccess>]
module MyModuleA =
let FetchResult id =
let result = AssemblyTwo.MyModuleC.FetchResult id
result
在
AssemblyTwo
中调用的函数在同一程序集中调用另一个函数(FetchActualResult()
),该函数采用属于所引用的C#DLL(MyCSharpType
)的MyCSharpLib
类型的参数:namespace AssemblyTwo
[<RequireQualifiedAccess>]
module MyModuleB =
let FetchActualResult(myCSharpType:MyCSharpLib.MyCSharpType, id:int)
//return a result
[<RequireQualifiedAccess>]
module MyModuleC =
let FetchResult id =
let myCSharpType = new MyCSharpLib.MyCSharpType()
MyModuleB.FetchActualResult(myCSharpType, id)
该解决方案可以在Visual Studio中编译和构建。但是,当我们尝试使用MSBuild从命令行构建项目时,构建会失败,并在msbuild.log中出现以下错误:
error FS0074: The type referenced through 'MyCSharpLib' is defined in an assembly that is not referenced. You must add a reference to assembly 'MyCSharpLib'.
似乎在
MyCSharpLib
的FetchActualResult()
函数签名中作为参数从AssemblyTwo
公开的类型导致了该错误。AssemblyOne
现在需要引用MyCSharpLib
,即使AssemblyOne
不直接使用MyCSharpLib
中的任何内容。如果我们从函数签名中删除参数,则解决方案将正确构建。
通过使用以下用例(“->”表示程序集引用)复制代码,我们进一步探讨了此问题:
AssemblyOne
-> F#AssemblyTwo
-> MyCSharpLib
(C#DLL)(不生成)AssemblyOne
-> F#AssemblyTwo
-> MyFSharpLib
(F#DLL)(不生成)AssemblyOne
-> F#AssemblyTwo
-> C#AssemblyThree
(在同一解决方案中组装)(不生成)AssemblyOne
-> F#AssemblyTwo
-> F#AssemblyThree
(在同一解决方案中进行组装)(内部版本)可以解释这种行为吗?
最佳答案
假设DWright指出您的源中有错别字,我想说这个错误可能是由于您使用此代码定义了带有外部类型MyCsharpType的公开方法参数的静态类MyModuleB所致。
这是Fsharp代码转换为IL的方式(从ILSpy-重新转换为Csharp):
...
public static class MyModuleB
{
public static string FetchActualResult(MyCSharpType myCSharpType, int id)
{
return myCSharpType.Fetch(id);
}
}
如果不公开该类型以使其静态可见,则可能不会出现该错误。但是,这将取决于编译器的实现。
我可以想象,在MyModuleA的编译过程中,编译过程或编译器版本的一种配置可以尝试“接触” MyModuleB,从而尝试达到未引用的参数类型,而其他配置可能不接触MyModuleB。这取决于。
因此,在我看来,问题似乎不在编译过程中,而是实际上,您公开了一种类型的用法,而该类型并未引用其汇编。