2

So, I was trying to get this simple test working in an F# console app:

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

I expected MEF to get the function properly resolved, but it doesn't. Instead, I get this:

An unhandled exception of type 'System.ComponentModel.Composition.CompositionContractMismatchException' occurred in System.ComponentModel.Composition.dll

Additional information:

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]'.

  • What am I missing here?
  • What is the difference between FSharpFunc(System.Int32, System.String) and FSharpFunc``2[System.Int32, System.String]?
  • What is the correct way to import/export F# functions via MEF?
Federico Berasategui
  • 43,562
  • 11
  • 100
  • 154

1 Answers1

3

The compiler turns top-level F# functions into methods, so your example will be compiled as:

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

This is probably causing the error. You can force the compiler to produce a property getter of FSharpFunc type by calling some operation that returns a function - even a simple identity function will don:

let makeFunc f = f 

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

I have not tested this, but I think it could work. That said, it is probably safer to go with a simple single-method interface in this case.

Tomas Petricek
  • 240,744
  • 19
  • 378
  • 553