F# では、次のような関数を作成できます。
let ``add x and y`` x y = x + y
そして、私は通常、次のように呼び出すことができます:
``add x and y`` 1 2
上記の関数を C# 側から呼び出す方法はありますか? しかし、オブジェクト ブラウザで見ることさえできませんでした。
CompiledName属性を使用して、有効なF# 関数名を任意の C# 有効な関数名として C# に公開できます。
namespace Library1
module Test =
[<CompiledName("Whatever")>]
let ``add a and b`` x y = x + y
そしてC#で:
using Library1;
...............
System.Console.WriteLine(Test.Whatever(2,2));
NickLからのコメントに関する2016 年 3 月 5 日のフォローアップは、少なくとも F#3.1 に適用されます。
関数からメンバーへの移行には、いくつかの「ifs and buts」が伴います。
そもそも、ピュアから使用された場合、CompiledName
アトリビュートはコンパイルされません。単なるコンパイルでは、.member
namespace
module
module
F# レコードのデコレートメソッド 内で使用するとmember
、2 つのティック間の内容がどのように見えるかに関係なく、問題なく動作します。ただし、F# レコードの装飾プロパティ がクロス アセンブリで表示される場合は、ダブル ティック間の内容が正当な値の名前に似ている場合のみです。member
CompiledName
module M
type MyRecord =
{ myField: string }
[<CompiledName "Whatever">]
member x.``Blah Blah blah``() = x.myField
[<CompiledName "Another">]
member x.``ABC`` = x.myField
次に、C# から次のように動作します。
var recInC = new M.MyRecord("Testing...");
Console.WriteLine(recInC.Whatever());
Console.WriteLine(recInC.Another);
このような不一致は、潜在的な問題を引き起こします。
リフレクションが唯一の方法かもしれませんが、使いにくい必要はありません。リフレクションを行うには、すべてをクラス内にラップするだけです。
public static class MyModuleWrapper
{
// it would be easier to create a delegate once and reuse it
private static Lazy<Func<int, int, int>> addXAndY = new Lazy<Func<int, int, int>>(() =>
(Func<int, int, int>)Delegate.CreateDelegate(typeof(Func<int, int, int>), typeof(MyModule).GetMethod("add x and y"))
);
public static int AddXAndY(int x, int y)
{
return addXAndY.Value(x, y);
}
// pass other methods through.
public static int OtherMethod(int x, int y)
{
return MyModule.OtherMethod(x, y);
}
}
その後、通常どおり使用してください。
var sum = MyModuleWrapper.AddXAndY(1, 2);
var otherValue = MyModuleWrapper.OtherMethod(1, 2); // use the wrapper instead
何を変更する必要があるか、またはポリモーフィック型が含まれている場合はどのように変更する必要があるかはわかりませんが、アイデアを理解して必要な変更を適用できることを願っています.