В F # мы можем создать такую функцию:
let ``add x and y`` x y = x + y
И я могу назвать это обычно следующим образом:
``add x and y`` 1 2
Есть ли способ вызвать функцию выше со стороны С#? Я даже не видел его в обозревателе объектов.
В F # мы можем создать такую функцию:
let ``add x and y`` x y = x + y
И я могу назвать это обычно следующим образом:
``add x and y`` 1 2
Есть ли способ вызвать функцию выше со стороны С#? Я даже не видел его в обозревателе объектов.
Вы можете выставить любое valid имя функции F # на С# как любое имя функции С# с использованием атрибут CompiledName:
namespace Library1
module Test =
[<CompiledName("Whatever")>]
let ``add a and b`` x y = x + y
а затем в С#:
using Library1;
...............
System.Console.WriteLine(Test.Whatever(2,2));
FOLLOW-UP 03/05/2016 в комментарии от NickL применяется, по крайней мере, к F # 3.1:
Переход от функций к членам приводит к некоторым "ifs и buts".
Для начала атрибут CompiledName
не компилируется с помощью member
, если используется с чистым namespace
. Для простой компиляции требуется использовать в пределах module
.
При использовании в module
и методе декорирования member
записи F # он работает отлично, независимо от того, как выглядит содержимое между двумя тиками. Однако, когда украшающее свойство member
записи F # CompiledName
видится кросс-сборкой, только если содержимое между двойными тиками напоминает какое-то правовое значение:
module M
type MyRecord =
{ myField: string }
[<CompiledName "Whatever">]
member x.``Blah Blah blah``() = x.myField
[<CompiledName "Another">]
member x.``ABC`` = x.myField
а затем из С# выполняется следующее:
var recInC = new M.MyRecord("Testing...");
Console.WriteLine(recInC.Whatever());
Console.WriteLine(recInC.Another);
Такие несоответствия требуют потенциального issues.
Отражение может быть единственным способом, но он не должен быть уродливым в использовании. Просто оберните все это внутри класса, чтобы сделать отражение.
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
Я не уверен, что нужно изменить или как, если есть полиморфные типы, но, надеюсь, вы получите эту идею и можете применить необходимые изменения.