私たちのコード ベースの一部では、ライブラリの大部分が 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# アセンブリで実行し、問題のあるコードを取り除く必要がありました。もう 1 つの問題は、F# がメンバーの protected 修飾子を適切にサポートしていないことです (F# はそれらをパブリックにします)。そのため、保護されることを意図したクラス メンバーに掛けることができる属性を作成しました。次に、Cecil を使用してアセンブリを爆破し、属性を取り除き、それらのメンバーへのアクセスを保護されたものに変更するツールを作成しました (コードはここで受け入れられた回答にあります)。
AutoOpen については知りませんでしたが、同様の作業を行う必要があったため、次のような作業を行うレジストラントというクラスを作成しました。
type FSharpRegistrant() =
do
// do whatever I need to get going
次に、C# モジュール内の静的コンストラクターで、クラスを見つけるためにリフレクションを使用して F# 登録者をインスタンス化するコードをいくつか書きました (私のコード ベースでは C# コードが最初にビルドされ、F# コードが存在することをまったく知らないため)。これは多くのエラー チェックを伴う見苦しいコードですが、機能します。