實戰MEF(3):只導出類的成員


通過前面兩篇文章的介紹,相信各位會明白MEF中有不少實用價值。上一文中我們也討論了導入與導出,對於導出導入,今天我們再深入一點點,嗯,只是深入一點點而已,不會很難的,請大家務必放心,如果大家覺得看文章枯燥,不妨一邊喝牛奶一邊閱讀。

上一文中我們都是把整個類型(整個類)進行導出,不過有時候,我們可能會考慮只導出類的某些成員,比如某個屬性或某個字段等。

我們還是少說理論,免得大家喝不下牛奶,還是直接上菜吧。為了便於測試,以下示例把組件都寫在當前程序集中,也就是在同一個項目,然后用AssemblyCatalog來查找。

首先,定義一個公共接口IWork。

然后分別用兩個類來實現該接口。

 

接着,我們再定義一個總類,包含兩個屬性,分別返回FirstWork類和SecondWork類的實例。

ExportAttribute特性只附加在WorkFirst和WorkSecond兩個屬性上,Works類只導出這兩個屬性。

隨后,我們組裝並調用這些導出部件。

然后我們運行一下示例,就可以得到如下圖所示的結果:

很多人學習編程很喜歡直接Ctrl + C別人的代碼,這是一種相當不好的學習方法,所以我把代碼都弄成截圖了,哈哈。

我事前在導入字段聲明時用了Lazy<T>,但發現不能創建對象,可能的原因是我們導出的是類的一部分,內部運行時在組裝部件時需要Works類進行實例化,因為如果Works對象不實例化的話,就導不出WorkFirst和WorkSecond屬性了。也許是這個原因導致的吧。

這時候大家可能會想,如果我在Works類中定義一個方法,我想導出這個方法怎么辦?

既然想到了還等什么,馬上試試就知道了,我們把Works類的代碼改一下,導出一個ViewWork方法。

協定類型為什么使用Func<TResult>呢?為什么,大家好好思考一下,用什么方式來表示方法的簽名與形式最形象?想想吧。

接着我們在Program類中導入這個方法。

導入的協定名與協定類型一定要與導出匹配,否則無法導入。這就好比你的言行要匹配一樣,否則妹子不會理你。

在完成組裝的代碼后面,我們測試調用導入的方法。

然后運行一下,看看有沒有結果。

不過,最后,還是把完整的代碼貼一下。

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using System.ComponentModel.Composition;

using System.ComponentModel.Composition.Hosting;

using System.Reflection;

 

namespace MefApp

{

// 作為公共接口

public interface IWork

{

void DoSome();

string WName { get; }

}

 

// 第一個實現公共接口的類

public class FirstWork : IWork

{

public void DoSome()

{

Console.WriteLine("工序一執行。");

}

 

public string WName

{

get { return "工序一"; }

}

}

 

// 第二個實現公共接口的類

public class SecondWork : IWork

{

 

public void DoSome()

{

Console.WriteLine("工序二執行。");

}

 

public string WName

{

get { return "工序二"; }

}

}

 

// 只對成員進行導出的類

public class Works

{

FirstWork fw;

SecondWork sw;

 

public Works()

{

// 初始化

fw = new FirstWork();

sw = new SecondWork();

}

 

// 該屬性被導出

[Export("work 1", typeof(IWork))]

public IWork WorkFirst { get {

return fw;

} }

 

// 該屬性被導出

[Export("work 2", typeof(IWork))]

public IWork WorkSecond

{

get { return sw; }

}

 

// 導出方法

[Export("view work", typeof(Func<string>))]

public string ViewWork()

{

return "本生產線國際一流,由3172個工作單元組成,73265道工序。";

}

}

 

class Program

{

// 導入

[Import("work 1", typeof(IWork))]

public IWork TheImportFirstWork;

 

// 導入

[Import("work 2", typeof(IWork))]

public IWork TheImportSecondWork;

 

// 導入

[Import("view work", typeof(Func<string>))]

public Func<string> TheImportViewWorkMethod;

 

static void Main(string[] args)

{

// 從當前程序集中發現組件

AssemblyCatalog cat = new AssemblyCatalog(typeof(Program).Assembly);

Program p = new Program();

CompositionContainer container = new CompositionContainer(cat);

container.SatisfyImportsOnce(p);//給合

 

// 調用測試

if (p.TheImportFirstWork!=null)

{

Console.Write("類型名:{0} Name:{1} 調用結果:",

p.TheImportFirstWork.GetType().Name,

p.TheImportFirstWork.WName);

p.TheImportFirstWork.DoSome();

}

if (p.TheImportSecondWork != null)

{

Console.Write("類型名:{0} Name:{1} 調用結果:",

p.TheImportSecondWork.GetType().Name,

p.TheImportSecondWork.WName);

p.TheImportSecondWork.DoSome();

}

if (p.TheImportViewWorkMethod != null)

{

Console.WriteLine(p.TheImportViewWorkMethod());

}

 

// 釋容器以及其創建的實例

container.Dispose();

Console.Read();

}

}

}


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com