zoukankan      html  css  js  c++  java
  • .Net插件编程模型:MEF和MAF[转载]

     

     

     

    .Net插件编程模型:MEF和MAF

           MEF和MAF都是C#下的插件编程框架,我们通过它们只需简单的配置下源代码就能轻松的实现插件编程概念,设计出可扩展的程序。这真是件美妙的事情!

    天抽了一点时间,看了看MEF的例子,比较简单,有时间会整理一个简单的例子出来。
    简单的说,MEF使用了两个标注实现依赖注入。

    [Export]可以指定输出的类或者属性
    [Import]可以指定引入

    通过Export,可以很轻松地将类或者属性输出到依赖注入的容器,再通过Export引入,对象的创建和组装,完全可以通过容器实现,并且可以通过[PartCreationPolicy(CreationPolicy.Shared)]标注,指定为单例模式。

    通过依赖注入,可以不必编写单例模式的代码。

     

    MEF(Managed Extensibility Framework)

                 MEF的工作原理大概是这样的:首先定义一个接口,用这个接口来约束插件需要具备的职责;然后在实现接口的程序方法上面添加反射标记“[Export()]”将实现的内容导出;最后在接口的调用程序中通过属性将插件加载进来。我们还是用代码来描述吧:

     

    1.  定义一个接口:

    [csharp] view plaincopyprint?
     
    1. /* 
    2.  
    3.     作者:GhostBear 
    4.     博客:http://blog.csdn.net/ghostbear   
    5.     简介:该节主要学习.net下的插件编程框架MEF(managed extensibility framework) 
    6.  
    7.  */  
    8.   
    9. using System;  
    10.   
    11. using System.Collections.Generic;  
    12.   
    13. using System.Linq;  
    14.   
    15. using System.Text;  
    16.   
    17.    
    18.   
    19. using System.Windows;  
    20.   
    21.    
    22.   
    23.    
    24.   
    25. namespace chapter28_simplecontract  
    26.   
    27. {  
    28.   
    29.     public interface ICalculator  
    30.   
    31.     {  
    32.   
    33.         IList<IOperation> GetOperations();  
    34.   
    35.         double Operate(IOperation operation, double[] operands);  
    36.   
    37.     }  
    38.   
    39.    
    40.   
    41.     public interface IOperation  
    42.   
    43.     {  
    44.   
    45.         string Name { get; }  
    46.   
    47.         int NumberOperands { get; }  
    48.   
    49.     }  
    50.   
    51.    
    52.   
    53.     public interface ICaculatorExtension  
    54.   
    55.     {  
    56.   
    57.         string Title { get; }  
    58.   
    59.         string Description { get; }  
    60.   
    61.         FrameworkElement GetUI();  
    62.   
    63.     }  
    64.   
    65. }  


     

     

     

    2.  实现定义的接口(部分一)

    [csharp] view plaincopyprint?
     
    1.     /* 
    2.        作者:GhostBear 
    3.        博客:http://blog.csdn.net/ghostbear 
    4.    */  
    [csharp] view plaincopyprint?
     
    1.     [Export(typeof(ICalculator))]  
    2.   
    3.     public class Caculator:ICalculator  
    4.   
    5.     {  
    6.   
    7.    
    8.   
    9.         public IList<IOperation> GetOperations()  
    10.   
    11.         {  
    12.   
    13.             return new List<IOperation>(){  
    14.   
    15.                 new Operation{ Name="+",NumberOperands=2},  
    16.   
    17.                 new Operation{Name="-",NumberOperands=2},  
    18.   
    19.                 new Operation{Name="*",NumberOperands=2},  
    20.   
    21.                 new Operation{Name="/",NumberOperands=2}  
    22.   
    23.             };  
    24.   
    25.         }  
    26.   
    27.    
    28.   
    29.         public double Operate(IOperation operation, double[] operands)  
    30.   
    31.         {  
    32.   
    33.             double result=0;  
    34.   
    35.             switch (operation.Name)  
    36.   
    37.             {   
    38.   
    39.                 case "+":  
    40.   
    41.                     result = operands[0] + operands[1];  
    42.   
    43.                     break;  
    44.   
    45.                 case "-":  
    46.   
    47.                     result = operands[0] - operands[1];  
    48.   
    49.                     break;  
    50.   
    51.                 case "*":  
    52.   
    53.                     result = operands[0] * operands[1];  
    54.   
    55.                     break;  
    56.   
    57.                 case "/":  
    58.   
    59.                     result = operands[0] / operands[1];  
    60.   
    61.                     break;  
    62.   
    63.                 default:  
    64.   
    65.                     throw new Exception("not provide this method");  
    66.   
    67.             }  
    68.   
    69.             return result;  
    70.   
    71.         }  
    72.   
    73. }  
    74.   
    75.    
    76.   
    77.     public class Operation:IOperation  
    78.   
    79.     {  
    80.   
    81.         public string Name  
    82.   
    83.         {  
    84.   
    85.             get;  
    86.   
    87.             internal set;  
    88.   
    89.         }  
    90.   
    91.    
    92.   
    93.         public int NumberOperands  
    94.   
    95.         {  
    96.   
    97.             get;  
    98.   
    99.             internal set;  
    100.   
    101.         }  
    102.   
    103.     }  


     

     

    实现定义的接口(部分二)

    [csharp] view plaincopyprint?
     
    1. /* 
    2.     作者:GhostBear 
    3.     博客:http://blog.csdn.net/ghostbear 
    4. */  
    5. [Export(typeof(ICalculator))]  
    6.   
    7.         public class Caculator : ICalculator  
    8.   
    9.         {  
    10.   
    11.    
    12.   
    13.             public IList<IOperation> GetOperations()  
    14.   
    15.             {  
    16.   
    17.                 return new List<IOperation>(){  
    18.   
    19.                 new Operation{ Name="+",NumberOperands=2},  
    20.   
    21.                 new Operation{Name="-",NumberOperands=2},  
    22.   
    23.                 new Operation{Name="*",NumberOperands=2},  
    24.   
    25.                 new Operation{Name="/",NumberOperands=2},  
    26.   
    27.                 new Operation{Name="%",NumberOperands=2},  
    28.   
    29.                 new Operation{Name="**",NumberOperands=1},  
    30.   
    31.                   
    32.   
    33.             };  
    34.   
    35.             }  
    36.   
    37.    
    38.   
    39.             public double Operate(IOperation operation, double[] operands)  
    40.   
    41.             {  
    42.   
    43.                 double result = 0;  
    44.   
    45.                 switch (operation.Name)  
    46.   
    47.                 {  
    48.   
    49.                     case "+":  
    50.   
    51.                         result = operands[0] + operands[1];  
    52.   
    53.                         break;  
    54.   
    55.                     case "-":  
    56.   
    57.                         result = operands[0] - operands[1];  
    58.   
    59.                         break;  
    60.   
    61.                     case "*":  
    62.   
    63.                         result = operands[0] * operands[1];  
    64.   
    65.                         break;  
    66.   
    67.                     case "/":  
    68.   
    69.                         result = operands[0] / operands[1];  
    70.   
    71.                         break;  
    72.   
    73.                     case "%":  
    74.   
    75.                         result=operands[0]%operands[1];  
    76.   
    77.                         break;  
    78.   
    79.                     case "**":  
    80.   
    81.                         result=operands[0]*operands[0];  
    82.   
    83.                         break;  
    84.   
    85.                     default:  
    86.   
    87.                         throw new Exception("not provide this method");  
    88.   
    89.                 }  
    90.   
    91.                 return result;  
    92.   
    93.             }  
    94.   
    95.         }  
    96.   
    97.    
    98.   
    99.         public class Operation : IOperation  
    100.   
    101.         {  
    102.   
    103.             public string Name  
    104.   
    105.             {  
    106.   
    107.                 get;  
    108.   
    109.                 internal set;  
    110.   
    111.             }  
    112.   
    113.    
    114.   
    115.             public int NumberOperands  
    116.   
    117.             {  
    118.   
    119.                 get;  
    120.   
    121.                 internal set;  
    122.   
    123.             }  
    124.   
    125.         }  
    126.   
    127.    


     

    分析:

         标记“[Export(typeof(ICalculator))]”声明表达的意思是:这个类可以编译为插件,并能放入插件容器“ICalculator”中。这里需要注意的是:部分一和部分二的代码分布在不同的程序集中。导出的插件不一定必须是以类的形式,也可以是方法。

     

     

    通过导出方法来生成插件:

    [csharp] view plaincopyprint?
     
    1.     /* 
    2.     作者:GhostBear 
    3.     博客:http://blog.csdn.net/ghostbear 
    4.    */  
    5. public class Bomb  
    6.   
    7.     {  
    8.   
    9.         [Export("Bomb")]  
    10.   
    11.         public void Fire()  
    12.   
    13.         {  
    14.   
    15.             Console.WriteLine("you are dead!!!");  
    16.   
    17.         }  
    18.   
    19.     }  


     

     

     

    插件的调用者:

    [csharp] view plaincopyprint?
     
    1. /* 
    2.  
    3.  
    4.     作者:GhostBear 
    5.     博客:http://blog.csdn.net/ghostbear 
    6.  
    7.  *  简介:该节主要学习.net下的插件编程框架MEF(managed extensibility framework) 
    8.  
    9.  */  
    10.   
    11. using System;  
    12.   
    13. using System.Collections.Generic;  
    14.   
    15. using System.Linq;  
    16.   
    17. using System.Text;  
    18.   
    19.    
    20.   
    21. using System.ComponentModel.Composition;  
    22.   
    23. using System.ComponentModel.Composition.Hosting;  
    24.   
    25.    
    26.   
    27. using chapter28_simplecontract;  
    28.   
    29.    
    30.   
    31. namespace chapter28  
    32.   
    33. {  
    34.   
    35.     class Program  
    36.   
    37.     {  
    38.   
    39.    
    40.   
    41.         [ImportMany(typeof(ICalculator))]  
    42.   
    43.         public IEnumerable<ICalculator> Calculators { getset; }  
    44.   
    45.    
    46.   
    47.         [Import("Bomb")]  
    48.   
    49.         public Action Bomb { getset; }  
    50.   
    51.    
    52.   
    53.    
    54.   
    55.           
    56.   
    57.         static void Main(string[] args)  
    58.   
    59.         {  
    60.   
    61.             Program pro = new Program();  
    62.   
    63.             pro.Run();  
    64.   
    65.             pro.Run2();  
    66.   
    67.         }  
    68.   
    69.    
    70.   
    71.         public void Run()  
    72.   
    73.         {  
    74.   
    75.             var catalog = new DirectoryCatalog("c:\plugins");  
    76.   
    77.             var container = new CompositionContainer(catalog);  
    78.   
    79.             try  
    80.   
    81.             {  
    82.   
    83.                 container.ComposeParts(this);  
    84.   
    85.             }  
    86.   
    87.             catch (Exception ex)  
    88.   
    89.             {  
    90.   
    91.                 Console.WriteLine(ex.Message);  
    92.   
    93.                 return;  
    94.   
    95.             }  
    96.   
    97.             ICalculator myCalculator = Calculators.ToList<ICalculator>()[1];  
    98.   
    99.               
    100.   
    101.    
    102.   
    103.             var operations = myCalculator.GetOperations();  
    104.   
    105.             var operationsDict = new SortedList<string, IOperation>();  
    106.   
    107.             foreach(IOperation item in operations)  
    108.   
    109.             {  
    110.   
    111.                 Console.WriteLine("Name:{0},number operands:{1}"  
    112.   
    113. , item.Name, item.NumberOperands);  
    114.   
    115.                 operationsDict.Add(item.Name, item);  
    116.   
    117.             }  
    118.   
    119.             Console.WriteLine();  
    120.   
    121.             string selectedOp = null;  
    122.   
    123.    
    124.   
    125.             do  
    126.   
    127.             {  
    128.   
    129.                 try  
    130.   
    131.                 {  
    132.   
    133.                     Console.Write("Operation?");  
    134.   
    135.                     selectedOp = Console.ReadLine();  
    136.   
    137.                     if (selectedOp.ToLower() == "exit"  
    138.   
    139.                                      || !operationsDict.ContainsKey(selectedOp))  
    140.   
    141.                     {  
    142.   
    143.                         continue;  
    144.   
    145.                     }  
    146.   
    147.                     var operation = operationsDict[selectedOp];  
    148.   
    149.                     double[] operands = new double[operation.NumberOperands];  
    150.   
    151.                     for (int i = 0; i < operation.NumberOperands; i++)  
    152.   
    153.                     {  
    154.   
    155.                         Console.WriteLine("  operand {0}?", i + 1);  
    156.   
    157.                         string selectedOperand = Console.ReadLine();  
    158.   
    159.                         operands[i] = double.Parse(selectedOperand);  
    160.   
    161.                     }  
    162.   
    163.                     Console.WriteLine("calling calculator");  
    164.   
    165.                     double result = myCalculator.Operate(operation, operands);  
    166.   
    167.                     Console.WriteLine("result:{0}", result);  
    168.   
    169.                 }  
    170.   
    171.                 catch (Exception ex)  
    172.   
    173.                 {  
    174.   
    175.                     Console.WriteLine(ex.Message);  
    176.   
    177.                     Console.WriteLine();  
    178.   
    179.                     continue;  
    180.   
    181.                 }  
    182.   
    183.             } while (selectedOp != "exit");  
    184.   
    185.         }  
    186.   
    187.    
    188.   
    189.         public void Run2()  
    190.   
    191.         {  
    192.   
    193.             var catalog = new DirectoryCatalog("c:\plugins");  
    194.   
    195.             var container = new CompositionContainer(catalog);  
    196.   
    197.    
    198.   
    199.             container.ComposeParts(this);  
    200.   
    201. Bomb.Invoke();  
    202.   
    203.             Console.ReadKey();  
    204.   
    205.         }  
    206.   
    207.     }  
    208.   
    209. }  


     

     

    分析:

       标记“[ImportMany(typeof(ICalculator))]”,该声明表达的意图是:将所有声明了标记“[Export(typeof(ICalculator))]”的程序集加载进容器。这里“[ImportMany]和”[Import]”的区别就是:前者的容器可以存放多个插件,而后者只能存放一个。

       光声明“[Import()]”和”[Export()]”标记是不行的,还必须通过下面的代码将这两个标记的功能联合起来:

               

    [csharp] view plaincopyprint?
     
    1.  //DirectoryCatalog表示这类插件会存放在系统的哪个文件夹下  
    2.   
    3. var catalog = new DirectoryCatalog("c:\plugins");  
    4.   
    5.             var container = new CompositionContainer(catalog);  
    6.   
    7.             try  
    8.   
    9.             {  
    10.   
    11. //将存放在目录中的插件按“[Export()]和[Import()]”规则装载进当前  
    12.   
    13. //类中。  
    14.   
    15.                 container.ComposeParts(this);  
    16.   
    17.             }  
    18.   
    19.             catch (Exception ex)  
    20.   
    21.             {  
    22.   
    23.                 Console.WriteLine(ex.Message);  
    24.   
    25.                 return;  
    26.   
    27.             }  


     

     

    执行结果

     Name:+,number operands:2

    Name:-,number operands:2

    Name:*,number operands:2

    Name:/,number operands:2

     

    Operation?+

             operand 1?

    1

             operand 2?

    1

    calling calculator

    result:2

    Operation?exit

     

     

    you are dead!!!

     

     

     

    MAF(Managed Addin Framework)

              MAF也是.Net为我们提供的一个“插件编程”解决方案。它比MEF复杂,需要配置很多元素。但它也有些优点:1.宿主程序和插件程序可以进行隔离,以此降低运行插件所带来的风险;2。MAF的设计是基于7个程序集组成的管道,这些管道部分可以单独更换,这些管道的详细情况见下图。

    图1

      

       使用MAF是需要有些细节需要注意:组成管道的7个程序集在系统中的保存路径有格式要求,并且没个保存它的文件夹内只运行同时出现一个程序集。具体情况如下图所示:

    图2

     

    图3

     

    图4

     

    图5

     

    下面我们来看一个小Demo吧,这个demo一共有7个项目,它们分别对应图1描述的管道中的7个部分。具体情况见下图。

     

    图6

     

     插件:Addin_1,Addin_2

    插件视图:AddinSideView

    插件适配器:AddinSideAdapter

    协定:IContract

    宿主视图:HostSideView

    宿主适配器:HostSideAdapter

    宿主程序:Host

     

    程序代码

     

    Addin_1

    [csharp] view plaincopyprint?
     
    1. /* 
    2.  
    3.  
    4.     作者:GhostBear 
    5.     博客:http://blog.csdn.net/ghostbear 
    6.     简介:测试MAF,这段代码是用来定义一个插件的。这个插件可以在宿主程序 
    7.      中动态加载。 
    8.  
    9.  */  
    10.   
    11. using System;  
    12.   
    13. using System.Collections.Generic;  
    14.   
    15. using System.Linq;  
    16.   
    17. using System.Text;  
    18.   
    19.    
    20.   
    21. using System.AddIn;  
    22.   
    23. using System.AddIn.Pipeline;  
    24.   
    25.    
    26.   
    27. namespace Addin_1  
    28.   
    29. {  
    30.   
    31. [AddIn("Helloworld",Description="this is helloworld addin"  
    32.   
    33. ,Publisher="GhostBear",Version="1.0")]  
    34.   
    35.     public class Addin_1:AddinSideView.AddinSideView  
    36.   
    37.     {  
    38.   
    39.    
    40.   
    41.         public string Say()  
    42.   
    43.         {  
    44.   
    45.             return "Helloworld";  
    46.   
    47.         }  
    48.   
    49.     }  
    50.   
    51. }  


     

     

    Addin_2

    [csharp] view plaincopyprint?
     
    1. /* 
    2.     作者:GhostBear 
    3.     博客:http://blog.csdn.net/ghostbear 
    4. */  
    5. using System;  
    6.   
    7. using System.Collections.Generic;  
    8.   
    9. using System.Linq;  
    10.   
    11. using System.Text;  
    12.   
    13.    
    14.   
    15. using System.AddIn;  
    16.   
    17.    
    18.   
    19. namespace Addin_2  
    20.   
    21. {  
    22.   
    23. [AddIn("SuperBomb",Description="This is a bigger bomb"  
    24.   
    25. ,Publisher="SuperWorker",Version="1.0.0.0")]  
    26.   
    27.     public class Addin_2:AddinSideView.AddinSideView  
    28.   
    29.     {  
    30.   
    31.         public string Say()  
    32.   
    33.         {  
    34.   
    35.             return "B--O--M--B";  
    36.   
    37.         }  
    38.   
    39.     }  
    40.   
    41. }  


     

     

     

    AddinSideView

     

    [csharp] view plaincopyprint?
     
    1. /* 
    2.  
    3.  
    4.     作者:GhostBear 
    5.     博客:http://blog.csdn.net/ghostbear 
    6.  
    7. *   简介:测试MAF,这段代码是定义插件端的视图类,该视图类的方法和属性必须与协定一致。 
    8.  
    9.  */  
    10.   
    11. using System;  
    12.   
    13. using System.Collections.Generic;  
    14.   
    15. using System.Linq;  
    16.   
    17. using System.Text;  
    18.   
    19.    
    20.   
    21.    
    22.   
    23. using System.AddIn.Pipeline;  
    24.   
    25. namespace AddinSideView  
    26.   
    27. {  
    28.   
    29.     [AddInBase()]  
    30.   
    31.     public interface AddinSideView  
    32.   
    33.     {  
    34.   
    35.         string Say();  
    36.   
    37.     }  
    38.   
    39. }  

     

     

    AddinSideAdapter

    [csharp] view plaincopyprint?
     
    1. /* 
    2.  
    3.  
    4.     作者:GhostBear 
    5.     博客:http://blog.csdn.net/ghostbear 
    6.  
    7. *   简介:测试MAF,这段代码是插件端的适配器类,它用来实现插件端视图类。 
    8.  
    9.  *         并组合协定。这样就能让插件和协定解耦,如果插件有所修改就换掉 
    10.  
    11.  *         该适配器类就可以了。 
    12.  
    13.  */  
    14.   
    15.    
    16.   
    17. using System;  
    18.   
    19. using System.Collections.Generic;  
    20.   
    21. using System.Linq;  
    22.   
    23. using System.Text;  
    24.   
    25.    
    26.   
    27. using System.AddIn.Pipeline;  
    28.   
    29.    
    30.   
    31.    
    32.   
    33. namespace AddinSideAdapter  
    34.   
    35. {  
    36.   
    37.     [AddInAdapter]  
    38.   
    39.     public class AddinSideAdapter : ContractBase,IContract.IMyContract  
    40.   
    41.     {  
    42.   
    43.         private AddinSideView.AddinSideView _handler;  
    44.   
    45.         public AddinSideAdapter(AddinSideView.AddinSideView handler)  
    46.   
    47.         {  
    48.   
    49.             this._handler = handler;  
    50.   
    51.         }  
    52.   
    53.    
    54.   
    55.         public string Say()  
    56.   
    57.         {  
    58.   
    59.             return this._handler.Say();  
    60.   
    61.         }  
    62.   
    63.     }  
    64.   
    65. }  
    66.   
    67.    


     

     

    IContract

    [csharp] view plaincopyprint?
     
    1. /* 
    2.  
    3.  
    4.     作者:GhostBear 
    5.     博客:http://blog.csdn.net/ghostbear 
    6.  
    7.      简介:测试MAF,这段代码是定义协定。 
    8.  
    9.  */  
    10.   
    11.    
    12.   
    13. using System;  
    14.   
    15. using System.Collections.Generic;  
    16.   
    17. using System.Linq;  
    18.   
    19. using System.Text;  
    20.   
    21.    
    22.   
    23. using System.AddIn.Pipeline;  
    24.   
    25. using System.AddIn.Contract;  
    26.   
    27.    
    28.   
    29. namespace IContract  
    30.   
    31. {  
    32.   
    33.     [AddInContract]  
    34.   
    35.     public interface IMyContract:System.AddIn.Contract.IContract  
    36.   
    37.     {  
    38.   
    39.         string Say();  
    40.   
    41.     }  
    42.   
    43. }  
    44.   
    45.    

     

     

    HostSideView

    [csharp] view plaincopyprint?
     
    1. /* 
    2.  
    3.  
    4.     作者:GhostBear 
    5.     博客:http://blog.csdn.net/ghostbear 
    6.  
    7.     简介:测试MAF,这段代码用来定义宿主段的视图类,该类的所有方法和属性需与协定类一致。 
    8.  
    9.  */  
    10.   
    11. using System;  
    12.   
    13. using System.Collections.Generic;  
    14.   
    15. using System.Linq;  
    16.   
    17. using System.Text;  
    18.   
    19.    
    20.   
    21. namespace HostSideView  
    22.   
    23. {  
    24.   
    25.     public interface HostSideView  
    26.   
    27.     {  
    28.   
    29.         string Say();  
    30.   
    31.     }  
    32.   
    33. }  


     

     

    HostSideAdapter

    [csharp] view plaincopyprint?
     
    1. /* 
    2.  
    3.     作者:GhostBear 
    4.     博客:http://blog.csdn.net/ghostbear 
    5.     简介:测试MAF,这段代码用来定义宿主端的适配器类。该类实现宿主端的 
    6.     视图类并组合协定。 
    7.  
    8.  */  
    9.   
    10.    
    11.   
    12. using System;  
    13.   
    14. using System.Collections.Generic;  
    15.   
    16. using System.Linq;  
    17.   
    18. using System.Text;  
    19.   
    20.    
    21.   
    22. using System.AddIn.Pipeline;  
    23.   
    24.    
    25.   
    26.    
    27.   
    28.    
    29.   
    30. namespace HostSideAdapter  
    31.   
    32. {  
    33.   
    34.     [HostAdapter()]  
    35.   
    36.     public class HostSideAdapter:HostSideView.HostSideView  
    37.   
    38.     {  
    39.   
    40.    
    41.   
    42.         private IContract.IMyContract _contract;  
    43.   
    44.         //这行代码重要  
    45.   
    46.         private System.AddIn.Pipeline.ContractHandle _handle;  
    47.   
    48.         public HostSideAdapter(IContract.IMyContract contract)  
    49.   
    50.         {  
    51.   
    52.             this._contract = contract;  
    53.   
    54.             this._handle = new ContractHandle(contract);  
    55.   
    56.           
    57.   
    58.         }  
    59.   
    60.    
    61.   
    62.    
    63.   
    64.         public string Say()  
    65.   
    66.         {  
    67.   
    68.             return this._contract.Say();  
    69.   
    70.         }  
    71.   
    72.     }  
    73.   
    74. }  
    75.   
    76.    


     

     

    Host

    [csharp] view plaincopyprint?
     
    1. /* 
    2.     作者:GhostBear 
    3.     博客:http://blog.csdn.net/ghostbear 
    4.     简介:测试MAF,这段代码是宿主程序。该程序可以针对保存在某个目录下的插件来进行选择性调用。 
    5.  
    6.  */  
    7.   
    8.    
    9.   
    10. using System;  
    11.   
    12. using System.Collections.Generic;  
    13.   
    14. using System.Linq;  
    15.   
    16. using System.Text;  
    17.   
    18.    
    19.   
    20.    
    21.   
    22. using System.Collections;  
    23.   
    24. using System.Collections.ObjectModel;  
    25.   
    26.    
    27.   
    28. using System.AddIn.Hosting;  
    29.   
    30.    
    31.   
    32. using HostSideView;  
    33.   
    34.    
    35.   
    36. namespace Host  
    37.   
    38. {  
    39.   
    40.     class Program  
    41.   
    42.     {  
    43.   
    44.         static void Main(string[] args)  
    45.   
    46.         {  
    47.   
    48.             string path = @"D:学习文档c#c#高级编程7MAFMAF";  
    49.   
    50.             string[] warnings = AddInStore.Update(path);  
    51.   
    52.    
    53.   
    54.             foreach (var tmp in warnings)  
    55.   
    56.             {  
    57.   
    58.                 Console.WriteLine(tmp);  
    59.   
    60.             }  
    61.   
    62.       //发现  
    63.   
    64.       var tokens = AddInStore.FindAddIns(typeof(HostSideView.HostSideView), path);  
    65.   
    66.    
    67.   
    68.             Console.WriteLine("当前共有{0}个插件可以选择。它们分别为:",tokens.Count);  
    69.   
    70.    
    71.   
    72.             var index = 1;  
    73.   
    74.             foreach (var tmp in tokens)  
    75.   
    76.             {  
    77.   
    78.                 Console.WriteLine(string.Format("[{4}]名称:{0},描述:{1},版本:{2},发布者:{3}", tmp.Name, tmp.Description, tmp.Version, tmp.Publisher,index++));  
    79.   
    80.             }  
    81.   
    82.    
    83.   
    84.    
    85.   
    86.             var token = ChooseCalculator(tokens);  
    87.   
    88.               
    89.   
    90. //隔离和激活插件  
    91.   
    92.             AddInProcess process=new AddInProcess(Platform.X64);  
    93.   
    94.             process.Start();  
    95.   
    96.             var addin = token.Activate<HostSideView.HostSideView>(process, AddInSecurityLevel.FullTrust);  
    97.   
    98.             Console.WriteLine("PID:{0}",process.ProcessId);  
    99.   
    100.             //调用插件  
    101.   
    102. Console.WriteLine(addin.Say());  
    103.   
    104.    
    105.   
    106.             Console.ReadKey();  
    107.   
    108.         }  
    109.   
    110.    
    111.   
    112.         private static AddInToken ChooseCalculator(Collection<AddInToken> tokens)  
    113.   
    114.         {  
    115.   
    116.             if (tokens.Count == 0)  
    117.   
    118.             {  
    119.   
    120.                 Console.WriteLine("No calculators are available");  
    121.   
    122.                 return null;  
    123.   
    124.             }  
    125.   
    126.             Console.WriteLine("Available Calculators: ");  
    127.   
    128.             // Show the token properties for each token in the AddInToken collection   
    129.   
    130.             // (tokens), preceded by the add-in number in [] brackets.  
    131.   
    132.             int tokNumber = 1;  
    133.   
    134.             foreach (AddInToken tok in tokens)  
    135.   
    136.             {  
    137.   
    138.                 Console.WriteLine(String.Format(" [{0}]: {1} - {2} {3}  {4}  {5} - {6}",  
    139.   
    140.                     tokNumber.ToString(),  
    141.   
    142.                     tok.Name,  
    143.   
    144.                     tok.AddInFullName,  
    145.   
    146.                     tok.AssemblyName,  
    147.   
    148.                     tok.Description,  
    149.   
    150.                     tok.Version,  
    151.   
    152.                     tok.Publisher));  
    153.   
    154.                 tokNumber++;  
    155.   
    156.             }  
    157.   
    158.             Console.WriteLine("Which calculator do you want to use?");  
    159.   
    160.             String line = Console.ReadLine();  
    161.   
    162.             int selection;  
    163.   
    164.             if (Int32.TryParse(line, out selection))  
    165.   
    166.             {  
    167.   
    168.                 if (selection <= tokens.Count)  
    169.   
    170.                 {  
    171.   
    172.                     return tokens[selection - 1];  
    173.   
    174.                 }  
    175.   
    176.             }  
    177.   
    178.             Console.WriteLine("Invalid selection: {0}. Please choose again.", line);  
    179.   
    180.             return ChooseCalculator(tokens);  
    181.   
    182.         }  
    183.   
    184.     }  
    185.   
    186. }  
    187.   
    188.    

    分析

        在上面的7个程序集,起解耦作用的关键还是2个适配器类。调用程序不直接调用协定,而是通过通过调用这2个适配器来间接调用协定。

     

     

     

     

     

     

     

    小结

        MEF和MAF为我们实现“插件编程”提供了2中选择,它们设计的出发点也是完全不同的。在使用它们的时候还是需要更加具体需求来权衡使用。

     

  • 相关阅读:
    CodeForces Gym 100935G Board Game DFS
    CodeForces 493D Vasya and Chess 简单博弈
    CodeForces Gym 100935D Enormous Carpet 快速幂取模
    CodeForces Gym 100935E Pairs
    CodeForces Gym 100935C OCR (水
    CodeForces Gym 100935B Weird Cryptography
    HDU-敌兵布阵
    HDU-Minimum Inversion Number(最小逆序数)
    七月馒头
    非常可乐
  • 原文地址:https://www.cnblogs.com/fx2008/p/3427968.html
Copyright © 2011-2022 走看看