【问题标题】:How to merge F# and C# assemblies with ILMerge so that all types would be available when referenced?如何将 F# 和 C# 程序集与 ILMerge 合并,以便在引用时所有类型都可用?
【发布时间】:2012-12-17 13:25:27
【问题描述】:

我有一个包含许多 F# 和 C# 项目的解决方案。我的目标是使用 ILMerge 将它们全部合并到一个库中。生成的合并 dll 将放入 NuGet 包并在其他项目中引用。但是,当 F# 项目中引用合并的 dll 时,我遇到了一些问题。

我遇到的问题是,如果提供给 ILMerge 的主程序集是 F#,那么在 F# 项目中引用生成的 dll 只允许访问 F# 类型。如果选择 C# dll 作为合并的主程序集,则在 F# 项目中引用时,合并的 F# 程序集的扩展方法不可用。在打开封闭命名空间时,具有AutoOpen 属性的模块也不再隐式打开。

有没有办法合并 F# 和 C# 程序集,以便所有类型(包括扩展方法)都可用?

【问题讨论】:

  • 你找到答案了吗?
  • 最后我决定不使用ILMerge。所以不幸的是,我没有成功合并 F# 和 C# 程序集的答案。

标签: c# f# ilmerge


【解决方案1】:

在我们的部分代码库中,库的很大一部分是在 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# 编译器中的一个错误,直到我们开始在混合中使用混淆功能,它要求我们在 F# 程序集上运行 ildasm 并删除有问题的代码。另一个问题是 F# 没有正确支持成员上的 protected 修饰符(F# 将它们公开),因此我们创建了一个属性,我们可以将其挂在本应受保护的类成员上。然后我们编写了一个工具,使用 Cecil 将程序集拆开,删除我们的属性并将对这些成员的访问更改为受保护 (code is in the accepted answer here)。

我不知道 AutoOpen,但我必须做类似的任务,所以我创建了一个名为 registrant 的类,它可以像这样完成此类工作:

type FSharpRegistrant() =
    do
        // do whatever I need to get going

然后在 C# 模块中的静态构造函数中,我编写了一些代码,使用反射来实例化 F# 注册者以查找类(因为在我的代码库中,C# 代码首先构建并且根本不知道有 F# 代码) .这是带有大量错误检查的丑陋代码,但它确实有效。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-03
    • 1970-01-01
    • 2012-07-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多