向 F# 传递 C# 接口/类

3

我有一个用C#编写的现有项目。我想将其中一部分业务逻辑移植到F#中。 MyObjectX是一个运行科学算法的C#类。 为了使MyObjectX运行,它需要实现一些接口,并通过方法注入一些依赖项(而不是构造函数)。例如:

public class MyObjectX(): IMathSolver, IBusinessSolver
{
    //private fields
    private int operationMode;
    private ISignalProvider signal;

    //Inject dependcy via method
    public void SetSignalProvider(ISignalProvider signal)
    {
        this.signal = signal;
    }

    //implemention of above interfaces
    public double MethodMathSolver()
    {
        this.signal.GetThreshold();
        //...
    }

    public double Method1BusinessSolver()
    {
    }

    public double Method2MathSolver(IResultProvider provider)
    {
        var x = provider.GetValueAtTime(0.1);
        //...
    }
}

现在我想在 F# 中实现 MyObjectX。如何以最大程度地使代码具有函数式,下面是三种方法:
  1. 将现有的 C# MyObjectX 作为包装器/外观器行为,放置在其他 C# 类和 F# 库之间,算法在 F# 模块中实现。

  2. 编写 F# MyObjectX 类来实现接口,可能调用其他 F# 模块。

  3. 或者以上两种都不是,请告知建议。

同时,如何传递 C# 的依赖项到 F# 中,例如 “IResultProvider/ISignalProvider”?是否需要使用可变变量通过 F# 函数填充依赖关系?
请建议并提供代码示例,谢谢。

我不懂 F#,但是所有的 CLR 语言都可以引用彼此的程序集,所以你应该能够从 F# 中“看到”所有 C# 对象,反之亦然。我怀疑这并没有回答你的问题,但希望能有所帮助! - BradleyDotNET
5个回答

6

我认为你可以在1和2之间进行选择,这两个选项肯定是最合理的。

我认为选项2可能更好,因为F#实现可以保持简单的F#模块,并使用最惯用的F#风格(例如将函数作为参数传递)。惯用的F#代码并不总是容易从C#中使用,因此如果你将其包装在实现所需C#接口的F#类中,则可以将“F#细节”隐藏起来,这是很好的。

看一下:


此外,可以查看我的回答,尝试将MyObjectX类翻译成F#。+1 - Mark Seemann
+1。我并不是专家,但当我创建一个既可以在 F# 库中使用,也可以在 C# 中使用的库时,我选择了第二个选项,这个选项在我的看法下工作得非常完美。 - Patryk Ćwiek

4

顺便提一下,MyObjectX 的(或多或少)直接翻译是

type MyObjectX() =
    let mutable operationMode = 0
    let mutable sp : ISignalProvider = Unchecked.defaultof<ISignalProvider>

    member this.SetSignalProvider signal = sp <- signal

    interface IMathSolver with
        member this.MethodMathSolver () = 
            sp.GetThreshold()
            //
            0.0
        member this.Method2MathSolver provider =
            let x = provider.GetValueAtTime 0.1
            //
            x

    interface IBusinessSolver with
        member this.Method1BusinessSolver () = 0.0

虽然我只能猜测一些接口定义,但这并不是特别实用。了解如何从面向对象转向面向函数的思维模式,请参阅以下链接:

2
只要接口在F#项目引用的程序集中定义,您可以直接实现MyObjectX
type MyObjectX(signal : ISignalProvider) = 
   let mutable operationMode : int = 0;   // assuming this changes

   interface IMathSolver with 
       member x.GetMethodMathSolver() : double =
          signal.GetThreshold()
          // ... 
       member x.MethodBusinessSolver() : double = 
          ... 

1
看看 F# 文档。可以轻松创建 .NET 类和接口,并在语言中使用它们。
如果您想使用 IoC,将 F# 实现注入到 C# 模块中或反之应该没有问题。试试吧!

1

我建议选择(1)。

这样,您在其他F#代码中引用F#时会更加方便,而且包装器应该很容易编写。这也会增加一层间接性,让您可以更改C#接口或F#代码而不影响系统的另一侧。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接