繁体   English   中英

从C#传递函数调用F#函数作为参数

[英]Call F# function from C# passing function as a parameter

我有以下F#功能

let Fetch logger id = 
    logger "string1" "string2"
    // search a database with the id and return a result

在我的C#类中,我想调用Fetch F#函数来模拟记录器函数。 所以我有以下C#函数作为mocker。

void Print(string x, string y) { // do nothing }

我正在尝试使用以下内容从C#类调用F#函数。

var _logger = FuncConvert.ToFSharpFunc<string, string>(Print);
var _result = Fetch(logger, 3);

FuncConvert.ToFSharpFunc的问题是只接受一个类型参数。 当我将Fetch F#记录器功能更改为以下内容时,当我使用ToFSharpFunc(打印)时,它可以正常工作,其中C#Print函数也包含一个字符串。

let Fetch logger id = 
    logger "string1"
    // search a database with the id and return a result

有人有想法吗?

简洁版本

var tupleLogger = FuncConvert.ToFSharpFunc<Tuple<string,string>>(t=>Print(t.Item1,t.Item2));
var logger = FuncConvert.FuncFromTupled(tupleLogger);

MyOtheProject.MyModule.Fetch(logger, 3);

长版

F#函数只接受一个参数。 多个参数本质上创建嵌套函数。 你需要在C#方面做同样的事情。

使用Intellisense检查C#中logger参数的类型。 它的

Microsoft.FSharp.Core.FSharpFunc<string, Microsoft.FSharp.Core.FSharpFunc<string, a>>

FuncConvert.ToFSharpFunc无法创建此。 但是, FuncFromTupled可以从FSharpFunc创建它,该FSharpFunc将带有多个字段的元组作为参数。

这是可以由ToFsharpFunc创建的东西:

FSharpFunc<Tuple<string,string>,Unit> tupleLogger = FuncConvert.ToFSharpFunc<Tuple<string,string>>(
       t=> Print(t.Item1,t.Item2));

要么

var tupleLogger = FuncConvert.ToFSharpFunc<Tuple<string,string>>(t=> Print(t.Item1,t.Item2));

正如FuncFromTupled的描述所说,它是A utility function to convert function values from tupled to curried form. tupleLogger是一个我们需要转换为curry形式的tupleLogger形式:

var logger = FuncConvert.FuncFromTupled(tupleLogger);

生成的代码如下所示:

var tupleLogger = FuncConvert.ToFSharpFunc<Tuple<string,string>>(t=>Print(t.Item1,t.Item2));
var logger = FuncConvert.FuncFromTupled(tupleLogger);

MyOtheProject.MyModule.Fetch(logger, 3);

您可以创建一个实用程序函数来组合两个转换:

public static class MyFuncConvert
{
    public static FSharpFunc<T1, FSharpFunc<T2, Unit>> ToFSharpFunc<T1, T2>(Action<T1, T2> action)
    {
        var tupled = FuncConvert.ToFSharpFunc<Tuple<T1, T2>>(
                                  t => action(t.Item1, t.Item2));
        var curried = FuncConvert.FuncFromTupled(tupled);
        return curried;
    }
}

这将允许你写:

var logger = MyFuncConvert.ToFSharpFunc<string,string>(Print);

F#函数只能有一个参数。 当你有例如: logger "string1" "string2" ,表达式logger "string1"会在其中创建另一个带有"string1"函数,然后可以将"string2"作为参数。 所以要转换它你可以创建这样的辅助方法:

public static class FuncConvertExt
{
    public static FSharpFunc<T1, FSharpFunc<T2, Unit>> Create<T1, T2>(Action<T1, T2> action)
    {
        Converter<T1, FSharpFunc<T2, Unit>> conv = value1 =>
        {
            return FuncConvert.ToFSharpFunc<T2>(value2 => action(value1, value2));
        };

        return FSharpFunc<T1, FSharpFunc<T2, Unit>>.FromConverter(conv);
    }
}     

然后你可以这样做:

var func = FuncConvertExt.Create<string, string>(Print);
func.Invoke("aaa").Invoke("bbb");

更多信息: https//blogs.msdn.microsoft.com/jaredpar/2010/07/27/converting-system-funct1-tn-to-fsharpfuncttresult/

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM