程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> 關於C# >> 實戰MEF(3)只導出類的成員

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

編輯:關於C#

通過前面兩篇文章的介紹,相信各位會明白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();
   
}
   
}
   
}
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved