C#在MEF框架中手動導(dǎo)入依賴模塊
對于簡單的場景來講,在MEF中導(dǎo)入依賴模塊非常簡單,只要用ImportAttribute標(biāo)記依賴的成員,MEF模塊會自動找到并創(chuàng)建該模塊。但有的時候我們依賴的模塊是上下文相關(guān)的,此時MEF框架的自動組裝滿足不了我們的需求了,這里以我之前的文章的一個Log插件為例:
class HostModule
{
[Import]
ILogger logger = null;
public string Name { get; private set; }
public HostModule(string name)
{
this.Name = name;
Compose();
logger.LogMessage("hello world");
}
void Compose()
{
var catalog = new AssemblyCatalog(this.GetType().Assembly);
var container = new CompositionContainer(catalog);
container.ComposeParts(this);
}
}
interface ILogger
{
void LogMessage(string msg);
}
[Export(typeof(ILogger))]
class ConsoleLogger : ILogger
{
public void LogMessage(string msg)
{
Console.WriteLine(DateTime.Now + ": " + msg);
}
}現(xiàn)在我想要在Log信息中加入模塊名稱作為前綴,改成如下形式:
[Export(typeof(ILogger))]
class ConsoleLogger : ILogger
{
public string ModuleName { get; private set; }
public void LogMessage(string msg)
{
Console.WriteLine(">> " + ModuleName + " | " + DateTime.Now + ": " + msg);
}
}由于MEF框架不知道Logger.ModuleName和HostModule.Name的關(guān)系,無法直接通過ImportAttribute標(biāo)記ModuleName屬性搞定。那么,我們該如何傳入這ModuleName呢?
通過構(gòu)造函數(shù)導(dǎo)入:
這最直接想到的就是一種方式了,主要修改如下:
在插件模塊中創(chuàng)建構(gòu)造函數(shù),參數(shù)為需要導(dǎo)入的依賴模塊,并且用ImportingConstructorAttribute標(biāo)記構(gòu)造函數(shù)。
在構(gòu)造函數(shù)中庸ImportAttribute標(biāo)記參數(shù)
在組裝函數(shù)中用ComposeExportedValue函數(shù)傳入?yún)?shù)
示例代碼如下:
class HostModule
{
[Import]
ILogger logger = null;
public string Name { get; private set; }
public HostModule(string name)
{
this.Name = name;
Compose();
logger.LogMessage("hello world");
}
void Compose()
{
var catalog = new AssemblyCatalog(this.GetType().Assembly);
var container = new CompositionContainer(catalog);
container.ComposeExportedValue("ModuleName", this.Name);
container.ComposeParts(this);
}
}
interface ILogger
{
void LogMessage(string msg);
}
[Export(typeof(ILogger))]
class ConsoleLogger : ILogger
{
public string ModuleName { get; private set; }
[ImportingConstructor]
public ConsoleLogger([Import("ModuleName")] string moduleName)
{
this.ModuleName = moduleName;
}
public void LogMessage(string msg)
{
Console.WriteLine(">> " + ModuleName + " | " + DateTime.Now + ": " + msg);
}
}這種方式一個比較大的缺點就是麻煩,上面的例子還好,如果要導(dǎo)入的參數(shù)比較多就顯得有點麻煩了。并且后續(xù)要新增一個依賴的模塊的話則要同時修改好幾處處地方,不夠集中,容易改漏,并且也不容易排查錯誤。
在成員中導(dǎo)入
在成員中導(dǎo)入的方式如下:
在Host中用Export標(biāo)記導(dǎo)出參數(shù)
在插件模塊中用Import標(biāo)記導(dǎo)入?yún)?shù)
修改后的代碼如下,我把修改的地方標(biāo)記了一下:
class HostModule
{
[Import]
ILogger logger = null;
[Export("ModuleName")]
public string Name { get; private set; }
public HostModule(string name)
{
this.Name = name;
Compose();
logger.LogMessage("hello world");
}
void Compose()
{
var catalog = new AssemblyCatalog(this.GetType().Assembly);
var container = new CompositionContainer(catalog);
container.ComposeParts(this);
}
}
interface ILogger
{
void LogMessage(string msg);
}
[Export(typeof(ILogger))]
class ConsoleLogger : ILogger
{
[Import("ModuleName")]
public string ModuleName { get; private set; }
public void LogMessage(string msg)
{
Console.WriteLine(">> " + ModuleName + " | " + DateTime.Now + ": " + msg);
}
}這種方式改動更少更直觀,擴(kuò)展性也更強(qiáng),要好用得多了。
進(jìn)一步解除限制
前面這種方式非常方便,但有一個限制:功能模塊是由MEF框架在組裝的時候創(chuàng)建的。但是,有的時候,功能模塊無法由MEF框架創(chuàng)建(例如在WPF程序中的UI對象,或者一些比較復(fù)雜的上下文相關(guān)對象),但是,這個時候我們?nèi)绾问謩訉?dǎo)入依賴的外部模塊呢?MEF框架本身也是提供了比較完善的解決方案的:在執(zhí)行ComposeParts函數(shù)組裝的時候?qū)蓚€對象一并傳入一起組裝即可。
class HostModule
{
ILogger logger = new ConsoleLogger();
[Export("ModuleName")]
public string Name { get; private set; }
public HostModule(string name)
{
this.Name = name;
Compose();
logger.LogMessage("hello world");
}
void Compose()
{
var container = new CompositionContainer();
container.ComposeParts(this, logger);
}
}
interface ILogger
{
void LogMessage(string msg);
}
class ConsoleLogger : ILogger
{
[Import("ModuleName")]
public string ModuleName { get; private set; }
public void LogMessage(string msg)
{
Console.WriteLine(">> " + ModuleName + " | " + DateTime.Now + ": " + msg);
}
}小結(jié):雖然前面介紹的這三種方式看起來有不小差別,但歸根結(jié)底只是不同的組裝形式而已,只要掌握了MEF的組裝原理,就可以非常自由的組裝我們所需要的模塊,實現(xiàn)松耦合、簡單化、模塊化的程序。
到此這篇關(guān)于C#在MEF框架中手動導(dǎo)入依賴模塊的文章就介紹到這了。希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C# Xamarin利用ZXing.Net.Mobile進(jìn)行掃碼的方法
這篇文章主要介紹了C# Xamarin利用ZXing.Net.Mobile進(jìn)行掃碼的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-06-06
C# Winform實現(xiàn)表格復(fù)制粘貼效果
這篇文章主要為大家學(xué)習(xí)介紹了如何通過C# Winform實現(xiàn)表格復(fù)制粘貼效果,文中的示例代碼講解詳細(xì),具有一定的參考價值,需要的可以了解一下2023-07-07
C#中數(shù)組初始化與數(shù)組元素復(fù)制的方法
這篇文章主要介紹了C#中數(shù)組初始化與數(shù)組元素復(fù)制的方法,涉及C#中數(shù)組的創(chuàng)建、初始化及使用Array.Copy方法復(fù)制數(shù)組元素的技巧,需要的朋友可以參考下2015-04-04
C#實現(xiàn)的微信網(wǎng)頁授權(quán)操作邏輯封裝示例
這篇文章主要介紹了C#實現(xiàn)的微信網(wǎng)頁授權(quán)操作邏輯封裝,分析了微信網(wǎng)頁授權(quán)操作的原理、步驟并給出了C#實現(xiàn)的網(wǎng)頁授權(quán)操作邏輯封裝類,需要的朋友可以參考下2016-10-10
C#雙向鏈表LinkedList排序?qū)崿F(xiàn)方法
這篇文章主要介紹了C#雙向鏈表LinkedList排序?qū)崿F(xiàn)方法,涉及C#雙向鏈表的定義與排序技巧,具有一定參考借鑒價值,需要的朋友可以參考下2015-08-08

