Reputation: 149020
I have this relatively simple program:
open System
open System.ComponentModel.Composition
open System.ComponentModel.Composition.Hosting
open System.Reflection
module Config =
[<Export("Timer.Delay")>]
let Delay = TimeSpan.FromSeconds(5.0)
[<EntryPoint>]
let main argv =
let catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly())
let container = new CompositionContainer(catalog)
let delay = container.GetExportedValue<TimeSpan> "Timer.Delay"
printfn "Delay: %A" delay
But I get this error on calling container.GetExportedValue<TimeSpan> "Timer.Delay"
:
More than one export was found that matches the constraint:
ContractName Timer.Delay
RequiredTypeIdentity System.TimeSpan
Inspecting the catalog.Parts
collection, I see two parts, each with a single ExportDefinition
. The first one for Program+Config
, which I would expect to find, and one for <StartupCode$Remote>.$Program
(note the assembly name is Remote
):
Wrapping the main
function in a module Program
does not change this behavior, nor does separating these modules into different files. Does anybody know why this F# program is generating a second export definition? And how can I prevent this?
Upvotes: 4
Views: 208
Reputation: 149020
After fiddling with it for a little bit, I think I've figured it out. My guess is that when the F# compiler sees an untargeted attribute on a property like the one above, it actually emits two attributes, one for the property and one for the field. It's probably also relevant that the ExportAttribute
may be applied to properties and fields. Specifying a target on the attribute seems to resolve this issue.
This will generate the Program+Config
part:
module Config =
[<property: Export("Timer.Delay")>]
let Delay = TimeSpan.FromSeconds(5.0)
This will generate the <StartupCode$Remote>.$Program
part:
module Config =
[<field: Export("Timer.Delay")>]
let Delay = TimeSpan.FromSeconds(5.0)
Both of these will solve my problem, but the first one seems better, since it binds the Export
attribute to a member of the actual module, rather than to some compiler-generated code.
Upvotes: 2