欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

基于MEF打造的插件系統(tǒng)的實現(xiàn)詳解

 更新時間:2013年05月13日 15:40:42   作者:  
最好自己動手實踐下MEF,不過講的都是MEF的基礎(chǔ),希望對你有所幫助

以實例說話,一起體驗MEF帶來的可擴展性吧,Let's Rock?。。?/FONT>

1:新建控制臺程序SimpleCalculator

image

在這里要實現(xiàn)的程序時SimpleCalculator,顧名思義:簡單的計算器。

所以我們需要定義一個用來計算的接口:

public interface ICalculator

{

    String Calculate(String input);

}

Program 的代碼如下:

class Program
{
    private CompositionContainer _container;

    [Import(typeof(ICalculator))]
    private ICalculator calculator;

    public Program()
    {
        //var catalog = new AggregateCatalog();
        //catalog.Catalogs.Add(new AssemblyCatalog(typeof(Program).Assembly));

        var catalog = new AssemblyCatalog(typeof(Program).Assembly);
        _container = new CompositionContainer(catalog);

        try
        {
            this._container.ComposeParts(this);
        }
        catch (CompositionException compositionException)
        {
            Console.WriteLine(compositionException.ToString());
        }
    }

    static void Main(string[] args)
    {
        Program p = new Program();
        string s;
        Console.WriteLine("Enter Command:");

        while (true)
        {
            s = Console.ReadLine();
            Console.WriteLine(p.calculator.Calculate(s));
        }
    }
}

MEF所要解決的是尋找插件的功能,傳統(tǒng)的實現(xiàn)插件的方式主要是使用接口,即聲明一個接口,然后使用配置文件來配置接口使用哪個實現(xiàn)類。

微軟知道有這種需求,于是提供了MEF來實現(xiàn)插件的功能。

Composite 原理

1:聲明一個 CompositionContainer 對象,這個對象里面包含一堆Catalog.

2:這堆Catalog如果是AssemblyCatalog,則在Assembly中查找,如果是DirectoryCatalog,

在Directory 中查找,如果即想要在Assembly中查找,又需要在Directory中查找,

則采用AggregateCatalog。

3:然后在這堆Catalog中查找與Import 特性相對應(yīng)的Export標(biāo)記所標(biāo)記的實現(xiàn)類,調(diào)用實現(xiàn)類的構(gòu)造函數(shù)進(jìn)行

Composite(組合)。

知道原理后,你也可以自己實現(xiàn)自己的CompositionContainer 類了,

要使用MEF 需要為SimpleCalculator添加 System.ComponentModel.Composition.dll 的引用,

然后導(dǎo)入命名空間:

using System.ComponentModel.Composition;

using System.ComponentModel.Composition.Hosting;

接下來看下Program 的構(gòu)造函數(shù)所做的事情:

聲明一個AssemblyCatalog,指向Program所在的Assembly. 然后把它添加到

CompositionContainer中,調(diào)用CompositionContainer 的ComposeParts 擴展方法,來Compose(this) 的Parts。

注:ComposeParts 是擴展方法,需要using System.ComponentModel.Composition;

OK,如何Compose,在哪個Assembly中查找實現(xiàn)類來進(jìn)行Compose已經(jīng)完成了。

目前的問題是:哪些類需要Compose??

為了回答這個問題,微軟提供了Import和Export特性: 

Import:哪個對象需要Compose。也就是需要被實現(xiàn)類給填充,所以Import標(biāo)記的是對象,一般該對象是接口,因為如果是具體類的話,那還需要Import嗎?

Export:哪個類可以被用來Compose,也就是說這個類是不是可以用來填充的實現(xiàn)類,所以Export標(biāo)記的是類,而不是具體的某個對象。

所以在這里calculator 使用Import 特性來標(biāo)記:

[Import(typeof(ICalculator))]

private ICalculator calculator;

接下來MEF 的組合引擎在ComposeParts(this)的時候,就會在catalog 代表的AssemblyCatalog中查找Export特性所修飾的實現(xiàn)類了,找到實現(xiàn)類后進(jìn)行Compose。

如果找不到Export特性修飾的類的話,結(jié)果如下:

image

OK,接下來添加一個實現(xiàn)類,并使用Export特性來進(jìn)行修飾:

[Export(typeof(ICalculator))]

 public class MySimpleCalculator : ICalculator

 {

     public string Calculate(string input)

     {

         return "MySimpleCalculator 處理了" + input;

     }

 }

運行結(jié)果如下:

image

當(dāng)然Import和Export還提供了其他的構(gòu)造函數(shù),所以你還可以將上面的Import和Export修改為:

[Import("calculator1", typeof(ICalculator))]

[Export("calculator1", typeof(ICalculator))]

之所以提供ContractName為calculator1 是因為你可能有多個ICalculator對象需要填充。

修改Program的代碼如下:

class Program

{

    private CompositionContainer _container;

    [Import("calculator1", typeof(ICalculator))]

    private ICalculator calculator1;

    [Import("calculator2", typeof(ICalculator))]

    private ICalculator calculator2;

    public Program()

    {

        //var catalog = new AggregateCatalog();

        //catalog.Catalogs.Add(new AssemblyCatalog(typeof(Program).Assembly));

        var catalog = new AssemblyCatalog(typeof(Program).Assembly);

        _container = new CompositionContainer(catalog);

        try

        {

            this._container.ComposeParts(this);

        }

        catch(CompositionException compositionException)

        {

            Console.WriteLine(compositionException.ToString());

        }

    }

    static void Main(string[] args)

    {

        Program p = new Program();

        string s;

        Console.WriteLine("Enter Command:");

        while (true)

        {

            s = Console.ReadLine();

            Console.WriteLine(p.calculator1.Calculate(s));

            Console.WriteLine(p.calculator2.Calculate(s));

        }

    }

}

修改Export修飾的類為:

[Export("calculator1", typeof(ICalculator))]

public class MySimpleCalculator1 : ICalculator

{

    public string Calculate(string input)

    {

        return "第一個Calculator 處理了" + input;

    }

}

[Export("calculator2", typeof(ICalculator))]

public class MySimpleCalculator2 : ICalculator

{

    public string Calculate(string input)

    {

        return "第二個Calculator 處理了" + input;

    }

}

運行結(jié)果如下:

image

因為Import和Export是一一對應(yīng)的,在現(xiàn)實世界中,存在著大量一對多的情況,微軟也預(yù)料到了這種情況,所以提供了ImportMany 特性。

在上個例子中的MySimpleCalculator的Calculate方法返回的是一句話,在這個例子中要真正實現(xiàn)計算的功能,例如輸入5+3,輸出8,輸入7*4,輸出28。

為了支持 + - * / 四種Operation.所以在MySimpleCalculator中聲明一個operations 的列表。

[Export(typeof(ICalculator))]

class MySimpleCalculator : ICalculator

{

    [ImportMany]

    IEnumerable<Lazy<IOperation, IOperationData>> operations;

    public string Calculate(string input)

        {

return "calculate 處理了" + input;

        }

}

之所以在MySimpleCalculator 中聲明operations ,是因為是計算器支持多種運算。因為operations 需要多個operation 來Compose(填充),所以使用ImportMany特性來修飾,和Import特性一樣,ImportMany特性一般也是修飾接口。

Ioperation 和IOperationData的定義如下:

public interface IOperation

{

    int Operate(int left, int right);

}

public interface IOperationData

{

    Char Symbol { get; }

}

Lazy<IOperation, IOperationData> operations:

提供對對象及其關(guān)聯(lián)的元數(shù)據(jù)的延遲間接引用,以供 Managed Extensibility Framework 使用。

意思是說IOperation 和IOperationData之間的引用需要延遲,為什么需要延遲?,因為IOperation需要根據(jù)IOperationData的Symbol符號來延遲創(chuàng)建。

也就是說,如果IOperationData的Symbol 等于 “+”,那么IOperation對象是AddOperation.如果IOperationData的Symbol等于”-”,那么IOperation對象是SubtractOperation.

那么如何保證這點呢?

關(guān)鍵點就在于ExportMetadata attribute 上。

看下Add Operation 的定義:

[Export(typeof(IOperation))]

[ExportMetadata("Symbol", '+')]

class Add : IOperation

{

    public int Operate(int left, int right)

    {

        return left + right;

    }

}

在這里ExportMetadata特性的Symbol 為+。所以當(dāng)IOperationData的Symbol為”+” 的時候,匹配的就是Add Operation

MySimpleCalculator 的完整代碼如下:

[Export(typeof(ICalculator))]

class MySimpleCalculator : ICalculator

{

    [ImportMany]

    IEnumerable<Lazy<IOperation, IOperationData>> operations;

    public string Calculate(string input)

        {

            int left;

            int right;

            char operation;

            int fn = FindFirstNonDigitPosition(input);

            if (fn < 0) return "Could not parse command.";

            try

            {

                left = int.Parse(input.Substring(0, fn));

                right = int.Parse(input.Substring(fn + 1));

            }

            catch

            {

                return "Could not parse command";

            }

            operation = input[fn];

            foreach (Lazy<IOperation, IOperationData> i in operations)

            {

                if (i.Metadata.Symbol.Equals(operation))

                    return i.Value.Operate(left, right).ToString();

            }

            return "Operation Not Found!";

        }

    private int FindFirstNonDigitPosition(string s)

    {

        for (int i = 0; i < s.Length; i++)

        {

            if (!(Char.IsDigit(s[i]))) return i;

        }

        return -1;

    }

}

回頭再看看上例的Program代碼:

class Program

{

    private CompositionContainer _container;

    [Import(typeof(ICalculator))]

    private ICalculator calculator;

    public Program()

    {

        //var catalog = new AggregateCatalog();

        //catalog.Catalogs.Add(new AssemblyCatalog(typeof(Program).Assembly));

        var catalog = new AssemblyCatalog(typeof(Program).Assembly);

        _container = new CompositionContainer(catalog);

        try

        {

            this._container.ComposeParts(this);

        }

        catch(CompositionException compositionException)

        {

            Console.WriteLine(compositionException.ToString());

        }

    }

    static void Main(string[] args)

    {

        Program p = new Program();

        string s;

        Console.WriteLine("Enter Command:");

        while (true)

        {

            s = Console.ReadLine();

            Console.WriteLine(p.calculator.Calculate(s));

        }

    }

}

當(dāng)this._container.ComposeParts(this); 的時候,MEF組合引擎就開始對標(biāo)記了Import特性的接口進(jìn)行Compose,所以在這里是calculator。在哪里找實現(xiàn)類呢?,AssemblyCatalog表明在Program的當(dāng)前Assembly中查找實現(xiàn)類,所以找到了MySimpleCalculator在構(gòu)造MySimpleCalculator 的時候,發(fā)現(xiàn)了ImportMany特性修飾的operations。于是繼續(xù)在AssemblyCatalog中找到了Add。

上面的過程是Compose的過程。

那么MySimpleCalculator 如何進(jìn)行Calculate的呢?

例如5+3

1:找出第一個非數(shù)字的位置,也就是需要找出 +。

2:聲明left,right.并且left 為5,right為3.

3:根據(jù)符號+來構(gòu)造IOperation對象,接著調(diào)用IOperation對象的Operate(left,right)方法。

foreach (Lazy<IOperation, IOperationData> i in operations)

 {

     if (i.Metadata.Symbol.Equals(operation))

         return i.Value.Operate(left, right).ToString();

 }

運行結(jié)果:

image

因為目前定義了Add 的Operation。所以根據(jù)符號+ 能夠找到Add,但是*我們沒有定義,所以O(shè)peration Not Found!.

于是開始定義Multiple:

[Export(typeof(IOperation))]

 [ExportMetadata("Symbol", '*')]

 class Multiple : IOperation

 {

     public int Operate(int left, int right)

     {

         return left * right;

     }

 }

再次運行,結(jié)果如下:

image

當(dāng)然還可以在當(dāng)前程序集下面增加- ,/,^,% 等Operation。

為了讓事情更加的有趣,我打算在Debug目錄下增加一個目錄CalculateExtensions,然后將-,/ ..的Operation放到里面來,讓MEF自動發(fā)現(xiàn)。

image

首先新建類庫項目:SimpleCalculatorExtension

因為需要實現(xiàn)IOperation ,所以需要添加對SimpleCalculator項目的引用。

因為需要Export特性,所以需要添加對System.ComponentModel.Composition的引用。

整個項目的結(jié)果如下:

image

Subtract代碼如下:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.ComponentModel.Composition;

namespace SimpleCalculatorExtension

{

    [Export(typeof(SimpleCalculator.IOperation))]

    [ExportMetadata("Symbol", '-')]

    class Subtract : SimpleCalculator.IOperation

    {

        public int Operate(int left, int right)

        {

            return left - right;

        }

    }

}

生成成功后,將SimpleCalculatorExtension.dll 拷貝到CalculateExtensions目錄下:

現(xiàn)在SimpleCalculator的Debug目錄應(yīng)該是這樣。

image

并且CalculateExtensions文件夾下面有SimpleCalculatorExtension.dll.

接下來唯一要修改的是Program的catalog 對象。

為了讓catalog既支持在Program的Assembly中查找,又支持在CalculateExtensions目錄下查找。修改代碼如下:

public Program()

 {

     var catalog = new AggregateCatalog();

     catalog.Catalogs.Add(new AssemblyCatalog(typeof(Program).Assembly));

     catalog.Catalogs.Add(new DirectoryCatalog("CalculateExtensions"));

     _container = new CompositionContainer(catalog);

     try

     {

         this._container.ComposeParts(this);

     }

     catch(CompositionException compositionException)

     {

         Console.WriteLine(compositionException.ToString());

     }

 }

運行結(jié)果如下:

image

修改SimpleCalculatorExtension 的Subtract方法為:

namespace SimpleCalculatorExtension

{

    [Export(typeof(SimpleCalculator.IOperation))]

    [ExportMetadata("Symbol", '-')]

    class Subtract : SimpleCalculator.IOperation

    {

        public int Operate(int left, int right)

        {

            Console.WriteLine("SimpleCalculatorExtension的方法");

            return left - right;

        }

    }

}

重新生成SimpleCalculatorExtension.dll 然后拷貝到CalculateExtensions 文件夾下:

再次運行程序,輸出入下:

image

文章有點長,而且有點亂,最好自己動手實踐下MEF,不過講的都是MEF的基礎(chǔ),希望對你有所幫助,另外如果你不使用MEF,采用面向接口的編程原則的話,相信你自己也很容易實現(xiàn)自己的“MEF”

】:

以實例說話,一起體驗MEF帶來的可擴展性吧,Let's Rock?。。?/STRONG>

1:新建控制臺程序SimpleCalculator

image

在這里要實現(xiàn)的程序時SimpleCalculator,顧名思義:簡單的計算器。

所以我們需要定義一個用來計算的接口:

public interface ICalculator

{

    String Calculate(String input);

}

Program 的代碼如下:

class Program
{
    private CompositionContainer _container;

    [Import(typeof(ICalculator))]
    private ICalculator calculator;

    public Program()
    {
        //var catalog = new AggregateCatalog();
        //catalog.Catalogs.Add(new AssemblyCatalog(typeof(Program).Assembly));

        var catalog = new AssemblyCatalog(typeof(Program).Assembly);
        _container = new CompositionContainer(catalog);

        try
        {
            this._container.ComposeParts(this);
        }
        catch (CompositionException compositionException)
        {
            Console.WriteLine(compositionException.ToString());
        }
    }

    static void Main(string[] args)
    {
        Program p = new Program();
        string s;
        Console.WriteLine("Enter Command:");

        while (true)
        {
            s = Console.ReadLine();
            Console.WriteLine(p.calculator.Calculate(s));
        }
    }
}

MEF所要解決的是尋找插件的功能,傳統(tǒng)的實現(xiàn)插件的方式主要是使用接口,即聲明一個接口,然后使用配置文件來配置接口使用哪個實現(xiàn)類。

微軟知道有這種需求,于是提供了MEF來實現(xiàn)插件的功能。

Composite 原理

1:聲明一個 CompositionContainer 對象,這個對象里面包含一堆Catalog.

2:這堆Catalog如果是AssemblyCatalog,則在Assembly中查找,如果是DirectoryCatalog,

在Directory 中查找,如果即想要在Assembly中查找,又需要在Directory中查找,

則采用AggregateCatalog。

3:然后在這堆Catalog中查找與Import 特性相對應(yīng)的Export標(biāo)記所標(biāo)記的實現(xiàn)類,調(diào)用實現(xiàn)類的構(gòu)造函數(shù)進(jìn)行

Composite(組合)。

知道原理后,你也可以自己實現(xiàn)自己的CompositionContainer 類了,

要使用MEF 需要為SimpleCalculator添加 System.ComponentModel.Composition.dll 的引用,

然后導(dǎo)入命名空間:

using System.ComponentModel.Composition;

using System.ComponentModel.Composition.Hosting;

接下來看下Program 的構(gòu)造函數(shù)所做的事情:

聲明一個AssemblyCatalog,指向Program所在的Assembly. 然后把它添加到

CompositionContainer中,調(diào)用CompositionContainer 的ComposeParts 擴展方法,來Compose(this) 的Parts。

注:ComposeParts 是擴展方法,需要using System.ComponentModel.Composition;

OK,如何Compose,在哪個Assembly中查找實現(xiàn)類來進(jìn)行Compose已經(jīng)完成了。

目前的問題是:哪些類需要Compose??

為了回答這個問題,微軟提供了Import和Export特性: 

Import:哪個對象需要Compose。也就是需要被實現(xiàn)類給填充,所以Import標(biāo)記的是對象,一般該對象是接口,因為如果是具體類的話,那還需要Import嗎?

Export:哪個類可以被用來Compose,也就是說這個類是不是可以用來填充的實現(xiàn)類,所以Export標(biāo)記的是類,而不是具體的某個對象。

所以在這里calculator 使用Import 特性來標(biāo)記:

[Import(typeof(ICalculator))]

private ICalculator calculator;

接下來MEF 的組合引擎在ComposeParts(this)的時候,就會在catalog 代表的AssemblyCatalog中查找Export特性所修飾的實現(xiàn)類了,找到實現(xiàn)類后進(jìn)行Compose。

如果找不到Export特性修飾的類的話,結(jié)果如下:

image

OK,接下來添加一個實現(xiàn)類,并使用Export特性來進(jìn)行修飾:

[Export(typeof(ICalculator))]

 public class MySimpleCalculator : ICalculator

 {

     public string Calculate(string input)

     {

         return "MySimpleCalculator 處理了" + input;

     }

 }

運行結(jié)果如下:

image

當(dāng)然Import和Export還提供了其他的構(gòu)造函數(shù),所以你還可以將上面的Import和Export修改為:

[Import("calculator1", typeof(ICalculator))]

[Export("calculator1", typeof(ICalculator))]

之所以提供ContractName為calculator1 是因為你可能有多個ICalculator對象需要填充。

修改Program的代碼如下:

class Program

{

    private CompositionContainer _container;

    [Import("calculator1", typeof(ICalculator))]

    private ICalculator calculator1;

    [Import("calculator2", typeof(ICalculator))]

    private ICalculator calculator2;

    public Program()

    {

        //var catalog = new AggregateCatalog();

        //catalog.Catalogs.Add(new AssemblyCatalog(typeof(Program).Assembly));

        var catalog = new AssemblyCatalog(typeof(Program).Assembly);

        _container = new CompositionContainer(catalog);

        try

        {

            this._container.ComposeParts(this);

        }

        catch(CompositionException compositionException)

        {

            Console.WriteLine(compositionException.ToString());

        }

    }

    static void Main(string[] args)

    {

        Program p = new Program();

        string s;

        Console.WriteLine("Enter Command:");

        while (true)

        {

            s = Console.ReadLine();

            Console.WriteLine(p.calculator1.Calculate(s));

            Console.WriteLine(p.calculator2.Calculate(s));

        }

    }

}

修改Export修飾的類為:

[Export("calculator1", typeof(ICalculator))]

public class MySimpleCalculator1 : ICalculator

{

    public string Calculate(string input)

    {

        return "第一個Calculator 處理了" + input;

    }

}

[Export("calculator2", typeof(ICalculator))]

public class MySimpleCalculator2 : ICalculator

{

    public string Calculate(string input)

    {

        return "第二個Calculator 處理了" + input;

    }

}

運行結(jié)果如下:

image

因為Import和Export是一一對應(yīng)的,在現(xiàn)實世界中,存在著大量一對多的情況,微軟也預(yù)料到了這種情況,所以提供了ImportMany 特性。

在上個例子中的MySimpleCalculator的Calculate方法返回的是一句話,在這個例子中要真正實現(xiàn)計算的功能,例如輸入5+3,輸出8,輸入7*4,輸出28。

為了支持 + - * / 四種Operation.所以在MySimpleCalculator中聲明一個operations 的列表。

[Export(typeof(ICalculator))]

class MySimpleCalculator : ICalculator

{

    [ImportMany]

    IEnumerable<Lazy<IOperation, IOperationData>> operations;

    public string Calculate(string input)

        {

return "calculate 處理了" + input;

        }

}

之所以在MySimpleCalculator 中聲明operations ,是因為是計算器支持多種運算。因為operations 需要多個operation 來Compose(填充),所以使用ImportMany特性來修飾,和Import特性一樣,ImportMany特性一般也是修飾接口。

Ioperation 和IOperationData的定義如下:

public interface IOperation

{

    int Operate(int left, int right);

}

public interface IOperationData

{

    Char Symbol { get; }

}

Lazy<IOperation, IOperationData> operations:

提供對對象及其關(guān)聯(lián)的元數(shù)據(jù)的延遲間接引用,以供 Managed Extensibility Framework 使用。

意思是說IOperation 和IOperationData之間的引用需要延遲,為什么需要延遲?,因為IOperation需要根據(jù)IOperationData的Symbol符號來延遲創(chuàng)建。

也就是說,如果IOperationData的Symbol 等于 “+”,那么IOperation對象是AddOperation.如果IOperationData的Symbol等于”-”,那么IOperation對象是SubtractOperation.

那么如何保證這點呢?

關(guān)鍵點就在于ExportMetadata attribute 上。

看下Add Operation 的定義:

[Export(typeof(IOperation))]

[ExportMetadata("Symbol", '+')]

class Add : IOperation

{

    public int Operate(int left, int right)

    {

        return left + right;

    }

}

在這里ExportMetadata特性的Symbol 為+。所以當(dāng)IOperationData的Symbol為”+” 的時候,匹配的就是Add Operation

MySimpleCalculator 的完整代碼如下:

[Export(typeof(ICalculator))]

class MySimpleCalculator : ICalculator

{

    [ImportMany]

    IEnumerable<Lazy<IOperation, IOperationData>> operations;

    public string Calculate(string input)

        {

            int left;

            int right;

            char operation;

            int fn = FindFirstNonDigitPosition(input);

            if (fn < 0) return "Could not parse command.";

            try

            {

                left = int.Parse(input.Substring(0, fn));

                right = int.Parse(input.Substring(fn + 1));

            }

            catch

            {

                return "Could not parse command";

            }

            operation = input[fn];

            foreach (Lazy<IOperation, IOperationData> i in operations)

            {

                if (i.Metadata.Symbol.Equals(operation))

                    return i.Value.Operate(left, right).ToString();

            }

            return "Operation Not Found!";

        }

    private int FindFirstNonDigitPosition(string s)

    {

        for (int i = 0; i < s.Length; i++)

        {

            if (!(Char.IsDigit(s[i]))) return i;

        }

        return -1;

    }

}

回頭再看看上例的Program代碼:

class Program

{

    private CompositionContainer _container;

    [Import(typeof(ICalculator))]

    private ICalculator calculator;

    public Program()

    {

        //var catalog = new AggregateCatalog();

        //catalog.Catalogs.Add(new AssemblyCatalog(typeof(Program).Assembly));

        var catalog = new AssemblyCatalog(typeof(Program).Assembly);

        _container = new CompositionContainer(catalog);

        try

        {

            this._container.ComposeParts(this);

        }

        catch(CompositionException compositionException)

        {

            Console.WriteLine(compositionException.ToString());

        }

    }

    static void Main(string[] args)

    {

        Program p = new Program();

        string s;

        Console.WriteLine("Enter Command:");

        while (true)

        {

            s = Console.ReadLine();

            Console.WriteLine(p.calculator.Calculate(s));

        }

    }

}

當(dāng)this._container.ComposeParts(this); 的時候,MEF組合引擎就開始對標(biāo)記了Import特性的接口進(jìn)行Compose,所以在這里是calculator。在哪里找實現(xiàn)類呢?,AssemblyCatalog表明在Program的當(dāng)前Assembly中查找實現(xiàn)類,所以找到了MySimpleCalculator在構(gòu)造MySimpleCalculator 的時候,發(fā)現(xiàn)了ImportMany特性修飾的operations。于是繼續(xù)在AssemblyCatalog中找到了Add。

上面的過程是Compose的過程。

那么MySimpleCalculator 如何進(jìn)行Calculate的呢?

例如5+3

1:找出第一個非數(shù)字的位置,也就是需要找出 +。

2:聲明left,right.并且left 為5,right為3.

3:根據(jù)符號+來構(gòu)造IOperation對象,接著調(diào)用IOperation對象的Operate(left,right)方法。

foreach (Lazy<IOperation, IOperationData> i in operations)

 {

     if (i.Metadata.Symbol.Equals(operation))

         return i.Value.Operate(left, right).ToString();

 }

運行結(jié)果:

image

因為目前定義了Add 的Operation。所以根據(jù)符號+ 能夠找到Add,但是*我們沒有定義,所以O(shè)peration Not Found!.

于是開始定義Multiple:

[Export(typeof(IOperation))]

 [ExportMetadata("Symbol", '*')]

 class Multiple : IOperation

 {

     public int Operate(int left, int right)

     {

         return left * right;

     }

 }

再次運行,結(jié)果如下:

image

當(dāng)然還可以在當(dāng)前程序集下面增加- ,/,^,% 等Operation。

為了讓事情更加的有趣,我打算在Debug目錄下增加一個目錄CalculateExtensions,然后將-,/ ..的Operation放到里面來,讓MEF自動發(fā)現(xiàn)。

image

首先新建類庫項目:SimpleCalculatorExtension

因為需要實現(xiàn)IOperation ,所以需要添加對SimpleCalculator項目的引用。

因為需要Export特性,所以需要添加對System.ComponentModel.Composition的引用。

整個項目的結(jié)果如下:

image

Subtract代碼如下:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.ComponentModel.Composition;

namespace SimpleCalculatorExtension

{

    [Export(typeof(SimpleCalculator.IOperation))]

    [ExportMetadata("Symbol", '-')]

    class Subtract : SimpleCalculator.IOperation

    {

        public int Operate(int left, int right)

        {

            return left - right;

        }

    }

}

生成成功后,將SimpleCalculatorExtension.dll 拷貝到CalculateExtensions目錄下:

現(xiàn)在SimpleCalculator的Debug目錄應(yīng)該是這樣。

image

并且CalculateExtensions文件夾下面有SimpleCalculatorExtension.dll.

接下來唯一要修改的是Program的catalog 對象。

為了讓catalog既支持在Program的Assembly中查找,又支持在CalculateExtensions目錄下查找。修改代碼如下:

public Program()

 {

     var catalog = new AggregateCatalog();

     catalog.Catalogs.Add(new AssemblyCatalog(typeof(Program).Assembly));

     catalog.Catalogs.Add(new DirectoryCatalog("CalculateExtensions"));

     _container = new CompositionContainer(catalog);

     try

     {

         this._container.ComposeParts(this);

     }

     catch(CompositionException compositionException)

     {

         Console.WriteLine(compositionException.ToString());

     }

 }

運行結(jié)果如下:

image

修改SimpleCalculatorExtension 的Subtract方法為:

namespace SimpleCalculatorExtension

{

    [Export(typeof(SimpleCalculator.IOperation))]

    [ExportMetadata("Symbol", '-')]

    class Subtract : SimpleCalculator.IOperation

    {

        public int Operate(int left, int right)

        {

            Console.WriteLine("SimpleCalculatorExtension的方法");

            return left - right;

        }

    }

}

重新生成SimpleCalculatorExtension.dll 然后拷貝到CalculateExtensions 文件夾下:

再次運行程序,輸出入下:

image

文章有點長,而且有點亂,最好自己動手實踐下MEF,不過講的都是MEF的基礎(chǔ),希望對你有所幫助,另外如果你不使用MEF,采用面向接口的編程原則的話,相信你自己也很容易實現(xiàn)自己的“MEF”

相關(guān)文章

最新評論