我有这个相对简单的程序:
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
但是我在调用container.GetExportedValue< TimeSpan>时遇到了这个错误. “Timer.Delay”:
More than one export was found that matches the constraint:
ContractName Timer.Delay
RequiredTypeIdentity System.TimeSpan
检查catalog.Parts集合,我看到两个部分,每个部分都有一个ExportDefinition.第一个是Program Config,我希望找到它,另一个用于< StartupCode $Remote>.$Program(注意程序集名称是Remote):
将主函数包装在模块程序中不会改变此行为,也不会将这些模块分成不同的文件.有人知道为什么这个F#程序正在生成第二个导出定义吗?我该如何防止这种情况?
最佳答案 在摆弄了一点之后,我想我已经弄明白了.我的猜测是,当F#编译器在上面的属性上看到一个非目标属性时,它实际上会发出两个属性,一个属性属性,一个属性为字段. ExportAttribute可能也适用于属性和字段.在属性上指定目标似乎可以解决此问题.
这将生成程序配置部分:
module Config =
[<property: Export("Timer.Delay")>]
let Delay = TimeSpan.FromSeconds(5.0)
这将生成< StartupCode $Remote>.$Program部分:
module Config =
[<field: Export("Timer.Delay")>]
let Delay = TimeSpan.FromSeconds(5.0)
这两个都将解决我的问题,但第一个似乎更好,因为它将Export属性绑定到实际模块的成员,而不是一些编译器生成的代码.