导致生成问题的 F# 程序集引用
本文关键字:程序集 引用 成问题 | 更新日期: 2023-09-27 18:32:52
我们有一个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 (MyCSharpLib
的 MyCSharpType
类型的参数:
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'.
在AssemblyTwo
FetchActualResult()
函数签名中作为MyCSharpLib
参数公开的类型似乎导致了错误。 AssemblyOne
现在需要引用MyCSharpLib
,即使AssemblyOne
没有直接使用MyCSharpLib
中的任何内容。如果我们从函数签名中删除参数,则解决方案构建时没有错误。
我们通过使用以下用例复制代码("->"表示程序集引用(进一步探讨了这个问题:
- F#
AssemblyOne
-> F#AssemblyTwo
->MyCSharpLib
(C# DLL( (不生成(
F# AssemblyTwo
->MyFSharpLib
(F# DLL( (不生成(
F# - F#
AssemblyTwo
-> C#AssemblyThree
(同一解决方案中的程序集((不生成(
F# AssemblyTwo
-> F#AssemblyThree
(同一解决方案中的程序集((生成(
AssemblyOne
-> F# AssemblyOne
-> AssemblyOne
-> F# 这种行为可以解释吗?
假设您的源代码中存在拼写错误,正如 DWright 指出的那样,我想说此错误可能只是因为通过此代码定义了一个静态类 MyModuleB,其中包含外部类型 MyCsharpType 的公开方法参数。
这就是Fsharp代码转换为IL的方式(从ILSpy - 重新翻译成Csharp(:
...
public static class MyModuleB
{
public static string FetchActualResult(MyCSharpType myCSharpType, int id)
{
return myCSharpType.Fetch(id);
}
}
如果不公开类型以使其静态可见,则可能不会显示错误。但是,这将取决于编译器的实现。
我可以想象,在编译MyModuleA的过程中,编译过程的一个配置或编译器的版本可以尝试"触摸"MyModuleB,从而尝试达到未引用的参数类型,而其他配置可能只是不接触MyModuleB。这要看情况。
因此,在我看来,问题不在于编译过程,而在于您公开了未引用其程序集的类型。
我刚才用这种方式解决了类似的情况。试试这个。
在 MyModuleC 的末尾,添加以下行:
let fetchResult = FetchResult
然后,在 MyModuleA 中,调用 fetchResult 而不是 FetchResult。当然有论据。
是的,我知道这听起来很傻,但一定要尝试。我相信它会打破不需要的依赖。
如果按原样使用 C# 中的 AssemblyTwo,则可能不会遇到此问题。当您使用 F# 中的 AssemblyTwo 时,它会浮出水面,所以我想知道 F# 编译器是否存在问题,或者它可能与超出我的柯里格式有关。无论如何,我希望 F# 编译器更聪明。也许有人应该提出问题,除非它已经完成。