在 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));
跟进03/05/2016 关于NickL的评论,至少适用于 F#3.1:
从功能转移到成员会带来一些“如果和但是”。
首先,如果从 pure 使用CompiledName
属性,则不会编译。单纯的编译需要在.member
namespace
module
在 F# 记录的module
装饰方法 member
中使用时,无论两个刻度之间的内容看起来如何,它都可以正常工作。但是,当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
我不确定需要更改什么或是否涉及多态类型,但希望您能理解并应用必要的更改。