F#和MEF:导出函数

时间:2016-02-21 23:39:44

标签: f# mef

所以,我试图让这个简单的测试在F#控制台应用程序中运行:

open System.Reflection
open System.ComponentModel.Composition
open System.ComponentModel.Composition.Hosting

[<Export(typeof<int -> string>)>]
let toString(i: int) = i.ToString()

[<EntryPoint>]
let main argv = 
    use catalog = new AssemblyCatalog(Assembly.GetEntryAssembly())
    use container = new CompositionContainer(catalog)

    let myFunction = container.GetExportedValue<int -> string>()
    let result = myFunction(5)
    0

我希望MEF能够正确解析该功能,但事实并非如此。 相反,我得到了这个:

  

未处理的类型异常   'System.ComponentModel.Composition.CompositionContractMismatchException'   发生在System.ComponentModel.Composition.dll

中      

其他信息:

     

Cannot cast the underlying exported value of type 'Program.toString (ContractName="Microsoft.FSharp.Core.FSharpFunc(System.Int32,System.String)")' to type 'Microsoft.FSharp.Core.FSharpFunc``2[System.Int32,System.String]'.

  • 我在这里缺少什么?
  • FSharpFunc(System.Int32, System.String)FSharpFunc``2[System.Int32, System.String]之间的区别是什么?
  • 通过MEF导入/导出F#功能的正确方法是什么?

1 个答案:

答案 0 :(得分:3)

编译器将顶级F#函数转换为方法,因此您的示例将编译为:

[Export(FSharpFunc<int,string>)]
public string toString(int i) { return i.ToString(); }

这可能导致错误。您可以强制编译器通过调用一些返回函数的操作来生成FSharpFunc类型的属性getter - 即使是简单的身份函数也不会:

let makeFunc f = f 

[<Export(typeof<int -> string>)>]
let toString = makeFunc <| fun (i:int) -> 
  i.ToString()

我没有对此进行测试,但我认为它可行。也就是说,在这种情况下使用简单的单方法接口可能更安全。