2014-05-07 74 views
4

我有這個相對簡單的程序:在F#重複MEF導出定義

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"此錯誤:

不止一個出口被發現,約束相匹配:

 合同名稱       &thinsp; Timer.Delay

    RequiredTypeIdentity System.TimeSpan

檢查的catalog.Parts收集,我看到兩個部分,各自具有單個ExportDefinition。第一個Program+Config,我希望找到,一個用於<StartupCode$Remote>.$Program(注意是集名稱爲Remote):

catalog.Parts

結束語在module Programmain功能不改變這種行爲,也沒有將這些模塊分成不同的文件。有人知道爲什麼這個F#程序正在生成第二個導出定義嗎?我怎樣才能防止這種情況?

回答

2

經過一段時間的擺弄之後,我想我已經明白了。我的猜測是,當F#編譯器在類似上面的屬性上看到一個非目標屬性時,它實際上會發出兩個屬性,一個屬性和一個字段。這可能也是相關的,ExportAttribute可能適用於屬性和領域。在屬性上指定目標似乎可以解決此問題。

這將產生Program+Config部分:

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屬性爲實際模塊的成員,而不是某些編譯器生成的代碼。