设计一个由C#调用的F#模块(Console / MVC / WPF)

时间:2022-09-01 09:32:42

I have been trying to use Deedle F# Library to write an F# batch program. It has worked perfectly. However, I am not sure about the best design for the following 2 tasks:

我一直在尝试使用Deedle F#Library编写一个F#批处理程序。它运作得很好。但是,我不确定以下两项任务的最佳设计:

  1. Combine the F# module into a existing ASP.net MVC/Web Api system

    将F#模块组合到现有的ASP.net MVC / Web Api系统中

  2. Create a WPF interface to serve as a control panel and visual dependency controller for the various F# modules.

    创建一个WPF接口,作为各种F#模块的控制面板和可视依赖控制器。

The type of tasks the F# modules are doing are processing time series and applying statistical processes to derive new time series.

F#模块正在执行的任务类型是处理时间序列并应用统计过程来推导新的时间序列。

I have been trying to create a class wrapper for the existing module so it can be called from C# code. I read from the C# Deep Dive that this is a better way to expose F# modules to C# callers.

我一直在尝试为现有模块创建一个类包装器,因此可以从C#代码中调用它。我从C#Deep Dive中读到,这是将F#模块暴露给C#调用者的更好方法。

The following is a sample wrapper:

以下是一个示例包装器:

type TimeSeriesDataProcessor(fileName:string) = 
        let mutable _fileName = fileName
        let _rawInputData = loadCsvFile _fileName
        let _pivotedData = _rawInputData 
                       |> pivotRawData 
                       |> fillPivotedRawData
                       |> calculateExpandingZscore

    //read and write 
    member this.FileName
        with get () = _fileName
        and set (value) = _fileName <- value
    member this.RawInputData
        with get () = _rawInputData
    member this.PivotedData
        with get () = _pivotedData
    member this.rawInputDataCount
        with get () = _rawInputData.RowCount
    member this.pivotedDataCount
        with get () = _pivotedData.RowCount

The following is a sample module where most of the logic should reside:

以下是大多数逻辑应驻留的示例模块:

 module Common = 

    let loadCsvFile (fileName:string ) : Frame<int,string> =
        let inputData = Frame.ReadCsv(fileName)
        inputData


    let pivotRawData inputData:Frame<DateTime,string> = 
        let pivotedData = inputData |> Frame.pivotTable (fun k r -> r.GetAs<DateTime>("Date"))  
                              (fun k r -> r.GetAs<string>("Indicator")) 
                              (fun f -> let maxVal = f?Value |> Stats.max 
                                        match maxVal with
                                        | Some mv -> mv
                                        | _ -> Double.NaN
                              )
        pivotedData

    let fillPivotedRawData inputData:Frame<DateTime,string> = 
        let filledA = inputData?A |> Series.fillMissing Direction.Forward
        inputData?A<-filledA
        let filledB = inputData?B |> Series.fillMissing Direction.Forward
        inputData?B<-filledB

        inputData

    let calculateExpandingZscore inputData:Frame<DateTime,string> = 
        let expandingMeanColA = inputData?A |> Stats.expandingMean
        let expandingMeanColB = inputData?B |> Stats.expandingMean
        let expandingStdevColA = inputData?A |> Stats.expandingStdDev
        let expandingStdevColB = inputData?B |> Stats.expandingStdDev
        let expandingZscoreColA = (inputData?A - expandingMeanColA)/expandingStdevColA
        let expandingZscoreColB = (inputData?B - expandingMeanColB)/expandingStdevColB
        inputData?ExpdingMeanA <- expandingMeanColA
        inputData?ExpdingMeanB <- expandingMeanColB
        inputData?ExpdingStdevA <- expandingStdevColA
        inputData?ExpdingStdevB <- expandingStdevColB
        inputData?ExpdingZscoreA <- expandingZscoreColA
        inputData?ExpdingZscoreB <- expandingZscoreColB
        inputData

I have been trying to use NUnit to serve as a C# caller. I found myself putting most of the logic in the class do/let binding. The member methods are serving as passing the results to the caller. I don't think my approach is correct.

我一直在尝试使用NUnit作为C#调用者。我发现自己把大部分逻辑都放在了类/ let绑定中。成员方法用于将结果传递给调用者。我不认为我的方法是正确的。

Can someone point me to the right direction? (I attempted to learn the F# WPF Framework on GitHub, but I am not yet up to the task)

有人能指出我正确的方向吗? (我试图在GitHub上学习F#WPF框架,但我还没有完成任务)

I am aware Deedle is also avalable for C#. But, I really want to use F#. The sample code actually has too many side effects.

我知道Deedle也可用于C#。但是,我真的想用F#。示例代码实际上有太多副作用。

1 个解决方案

#1


4  

To put it bluntly, you want to build as little of your UI and framework in F# as possible. As you have noted, F# is a great language when it's great; otherwise, it is not recommended for application building (some hardcore functional-language-fanboys might fight me on that, but I stand by it, haha).

说白了,你想尽可能少地在F#中构建你的UI和框架。正如你所指出的那样,当它很棒时,F#是一种很棒的语言;否则,它不建议用于应用程序构建(一些硬核功能语言 - 粉丝可能会打我,但我坚持,哈哈)。

I would recommend putting all of your unit-of-work F# code in a Portable F# Library (https://msdn.microsoft.com/en-us/library/hh913781.aspx). Then, referencing that library and calling methods from it is as simple as calling the classes and methods as you would from C# or VB classes and methods.

我建议将所有工作单元F#代码放在便携式F#库中(https://msdn.microsoft.com/en-us/library/hh913781.aspx)。然后,引用该库并从中调用方法就像调用C#或VB类和方法中的类和方法一样简单。

There are also some templates that you can use (http://blogs.msdn.com/b/mcsuksoldev/archive/2011/06/05/f-class-library-template.aspx).

您还可以使用一些模板(http://blogs.msdn.com/b/mcsuksoldev/archive/2011/06/05/f-class-library-template.aspx)。

#1


4  

To put it bluntly, you want to build as little of your UI and framework in F# as possible. As you have noted, F# is a great language when it's great; otherwise, it is not recommended for application building (some hardcore functional-language-fanboys might fight me on that, but I stand by it, haha).

说白了,你想尽可能少地在F#中构建你的UI和框架。正如你所指出的那样,当它很棒时,F#是一种很棒的语言;否则,它不建议用于应用程序构建(一些硬核功能语言 - 粉丝可能会打我,但我坚持,哈哈)。

I would recommend putting all of your unit-of-work F# code in a Portable F# Library (https://msdn.microsoft.com/en-us/library/hh913781.aspx). Then, referencing that library and calling methods from it is as simple as calling the classes and methods as you would from C# or VB classes and methods.

我建议将所有工作单元F#代码放在便携式F#库中(https://msdn.microsoft.com/en-us/library/hh913781.aspx)。然后,引用该库并从中调用方法就像调用C#或VB类和方法中的类和方法一样简单。

There are also some templates that you can use (http://blogs.msdn.com/b/mcsuksoldev/archive/2011/06/05/f-class-library-template.aspx).

您还可以使用一些模板(http://blogs.msdn.com/b/mcsuksoldev/archive/2011/06/05/f-class-library-template.aspx)。