在MEF中實現延遲載入部件

2021-09-06 19:15:41 字數 2935 閱讀 1369

在mef的宿主中,當我們通過import宣告匯入的物件時,組裝(compose)的時候會建立該物件。例如:

inte***ceilogger

[export(typeof(ilogger))]

classconsolelogger: ilogger

}classhost}

有的時候,有些元件的建立開銷比較大,但又不會立即使用。此時,我們希望通過延遲初始化的方式將其延遲到使用的時候建立,從而提高效能(常見的是提高啟動速度)。mef是支援這一模式的,我們只需要修改一下匯入的宣告形式即可。

[import]

lazy _logger = null;

這樣,logger就會延遲到第一次使用的時候建立了。

元資料metadata

有的時候,對於同乙個服務有多個提供者,我們需要從中選擇乙個使用。mef提供了importmany來解決這一需求。

[export(typeof(ilogger))]

classconsolelogger: ilogger

}[export(typeof(ilogger))]

classdblogger: ilogger

}classhost}

此時,如果我們想使用延遲匯入的時候,就會變成如下形式:

classhost}

咋一看並沒有什麼問題,所有的logger都是延遲建立的。但是仔細分析一下就會發現,要找到dblogger的時候,必須遍歷所有的_loggerservices,這個遍歷會導致建立logger。也就是說,使用第乙個logger的時候可能建立所有的logger。

那麼,如何實現我們只建立所需要的logger呢? 這個時候就輪到元資料出場了,mef中的元資料可以將乙個資料附加到export的服務物件中一併匯出,從而可以通過元素據找到對應的服務。首先我們看看最終的效果吧:

publicinte***ceiloggerdata

}classhost}

這裡首先宣告了乙個元資料型別的介面iloggerdata,然後,匯入的物件變成了lazy

,這個物件有乙個屬性為metadata,它的型別就是剛才宣告的iloggerdata。匯出的ilogger物件是延遲建立的,而元資料不是延遲建立的。我們可以通過遍歷iloggerdata來找到所需要的logger物件,從而實現只建立所使用的logger物件。

通過exportmetadataattribute標記宣告

這種方式是在匯出的服務的時候一併通過exportmetadataattribute屬性標記元素據:

[exportmetadata("name", "console logger")]

[export(typeof(ilogger))]

classconsolelogger: ilogger

}[exportmetadata("name", "db logger")]

[export(typeof(ilogger))]

classdblogger: ilogger}

exportmetadataattribute有兩個引數,name和value,name為屬性名稱,value為屬性值。compse的時候,mef會先建立乙個實現了元資料物件,然後將根據將value值賦值給name所對應的屬性名稱。

這麼做雖然比較簡單,但是它有兩個弊端:

1. 屬性名稱不是強型別

這裡我們必須字串來給標誌屬性名稱,它們之間並沒有語法級的一致性檢查,在缺少nameof運算子的現在,一旦元資料屬性名稱更改的話是非常容易出錯的。

2. 如果元資料有多個值的話賦值顯得非常累贅。

假如我們增加了乙個priority型別的屬性,

publicinte***ceiloggerdata

intpriority

}此時,必須對所有的匯出物件都增加乙個exportmetadata標記,寫出如下形式:

[exportmetadata("name", "db logger")]

[exportmetadata("priority", 3)]

當屬性更多一點的話相信程式設計師們就會罵娘了。並且一旦某個export物件漏寫了,改物件就不會被匯入。這個是乙個執行時的錯誤,非常不容易排查的。

通過attribute標記

這種方式可以通過乙個attribute來標記元資料:

[metadataattribute]

[attributeusage(attributetargets.class, inherited = false, allowmultiple = false)]

classloggerdataattribute: attribute, iloggerdata

publicloggerdataattribute(stringname)

}[loggerdata("console logger")]

[export(typeof(ilogger))]

classconsolelogger: ilogger, iloggerdata

publicvoidlog(stringmessage)

}[loggerdata("db logger")]

[export(typeof(ilogger))]

classdblogger: ilogger, iloggerdata

publicvoidlog(stringmessage)

} 首先,宣告乙個loggerdataattribute,這個attribute必須被metadataattribute標記。然後,在export的物件前加上該loggerdataattribute,這樣mef匯入的時候就會根據該loggerdataattribute建立元資料了。

值得一提的是,這裡的loggerdataattribute本身並不需要實現iloggerdata介面,它是乙個ducktype的約定,只需要實現元資料的屬性即可。我這裡實現該介面主要是為了讓編譯器保障元資料屬性都有被準確實現。

MyBatis延遲載入及在spring中整合配置

當你要使用one to one,many to one 就會碰到n 1的問題。很明顯,物件之間關聯很多有a關聯b,b關聯c,c關聯a這樣的關係,如果不是採用延遲載入,很容易一下在出現成千上萬物件,造成n 1的問題。而mybatis 設定延遲載入主要2個屬性配置 lazyloadingenabled ...

MEF在WebApi中應用

1.mef在mvc中和在webapi中的初始化,是用區別的,他們分別實現的介面如下 webapi需要實現的介面 mvc需要實現的介面 system.web.mvc.idependencyresolver 2.mef的 如下 3.在webapiconfig.cs檔案中,設定mef的初始化,如下 初始化...

Swift中的延遲載入 懶載入

而在swift中,你只需一行 即可實現此機制 lazy var players string 簡單 簡潔,直入主題。但你得記住,你必須使用var關鍵字來定義延遲載入的屬性,不能使用let關鍵字,因為常量必須在例項構建時賦值。lazy var players string 如果你願意,你也可以使用例項...