在我们的部分代码库中,库的很大一部分是在 F# 中完成的,其余的则在 C# 中完成。F# 和 C# 代码都是正面的。
我们有一个地狱般的批处理文件来处理合并,我看到的是我们正在与这段代码合并:
echo merging %mergeapp% /keyfile:"%keyfile%" /target:library /attr:"%dstpath%%csharpdll%" /targetplatform:%targetplatform%,%targetlib% /lib:%sllib% /lib:%targetlib% /lib:"%libpath%lib" /out:"%mergedpath%..\%csharpdll%" "%dstpath%%csharpdll%" "%dstpath%%fsharpdll%"
%mergeapp% /keyfile:"%keyfile%" /target:library /attr:"%dstpath%%csharpdll%" /targetplatform:%targetplatform%,%targetlib% /lib:%sllib% /lib:%targetlib% /lib:"%libpath%lib" /out:"%mergedpath%..\%csharpdll%" "%dstpath%%csharpdll%" "%dstpath%%fsharpdll%"
这就是我们想要的。但是,我们不发布任何扩展方法,也不做任何 AutoOpen。我们发现了 F# 编译器中的一个错误,直到我们开始在混合中加入混淆,它要求我们ildasm
在 F# 程序集上运行并删除有问题的代码。另一个问题是 F# 没有正确支持成员上的 protected 修饰符(F# 将它们公开),因此我们创建了一个属性,我们可以将其挂在本应受保护的类成员上。然后我们编写了一个工具,使用 Cecil 将程序集拆开,删除我们的属性并将对这些成员的访问更改为受保护(代码在此处接受的答案中)。
我不知道 AutoOpen,但我必须做类似的任务,所以我创建了一个名为 registrant 的类,它可以像这样完成这样的工作:
type FSharpRegistrant() =
do
// do whatever I need to get going
然后在 C# 模块中的静态构造函数中,我编写了一些代码,使用反射来实例化 F# 注册者以查找类(因为在我的代码库中,C# 代码首先构建并且根本不知道有 F# 代码)。这是带有大量错误检查的丑陋代码,但它可以工作。