RogerTong's Tech Space

文章书傲骨,程序写春秋

导航

Mussel使用系列(五):插件项目之间的调用

Posted on 2008-07-09 16:40  RogerTong  阅读(444)  评论(0编辑  收藏  举报

在上一篇文章中,我们讲过如何从外部调用插件项目,接下来我们来看看插件项目与插件项目之间的调用。

我们来看看现在的应用场景:同样是对两个数值进行运算,MathOne是基本并且稳定的运算服务,负责对这两个数据相加并返回值。但是由于新的用户的需求发生了改变,他们希望获得的值是MathOne结果的平方数,例如:

如果我们传入的值是 (2,3),旧用户期望得到的值是 2+3 = 5 ,而新用户期望的值是  MathOne 运算结果的平方数,即是 5  2 = 25。

由于需要同时考虑新的需求并兼容旧的用户,所以我们需要加多一个插件项来为新用户响应需求。

为了让大家看起来不那么吃力,我们还是重述一下相关的接口及 MathOne 的实现:

 

运算服务的接口定义(程序集:Unit.Contract.dll)
  1. namespace Unit   
  2. {   
  3.     public interface IMath   
  4.     {   
  5.         int Calculate(int value1, int value2);   
  6.     }   
  7. }  

 

MathOne - 旧用户用到的运算服务(Unit.MathOne.dll)
  1. using System;   
  2. using Mussel.Addins;   
  3.   
  4. namespace Unit   
  5. {   
  6.     [MusselType("MathOne")]   
  7.     public class MathOne:AddinItem,IMath   
  8.     {   
  9.         public int Calculate(int value1, int value2)   
  10.         {   
  11.             Console.WriteLine("MathOne Calculate:");   
  12.             Console.WriteLine("\t{0} + {1} = {2}",   
  13.                 value1, value2, value1 + value2);   
  14.             return value1 + value2;   
  15.         }   
  16.     }   
  17. }  

 

我们再来看看新的运算服务实现:

MathTwo - 新的运算服务(Unit.MathTwo.dll)
  1. using System;   
  2. using Mussel.Addins;   
  3.   
  4. namespace Unit   
  5. {   
  6.     [MusselType("MathTwo")]   
  7.     public class MathTwo:AddinItem,IMath   
  8.     {   
  9.         private string mathOneKey;   
  10.   
  11.         protected string MathOneKey   
  12.         {   
  13.             get { return ReadProperty(ref mathOneKey, "MathOne"); }   
  14.         }   
  15.   
  16.   
  17.         public int Calculate(int value1, int value2)   
  18.         {   
  19.             Console.WriteLine("MathTwo Calculate:");   
  20.   
  21.             IMath mathOne = FindAddinItem<IMath>(MathOneKey);   
  22.             int result = mathOne.Calculate(value1, value2);   
  23.                
  24.             Console.WriteLine("\t{0} * {0} = {1}",   
  25.                 result,result * result);   
  26.                
  27.             return result * result;   
  28.         }   
  29.     }   
  30. }  

由于我们需要知道旧的运算服务 - MathOne 插件项目的具体路径,所以,我们引入了一个MathOneKey 的属性,这个属性从插件配置文件(*.addin)中对应的插件项目配置节点来读取相应的特性,用ReadProperty函数读取。ReadProperty函数其实是封装了经典的Double Lock方式,也可以看一下原码:

C#代码
  1. protected string ReadProperty(ref string field,    
  2.     string propertyName)   
  3. {   
  4.     return ReadProperty(ref field, propertyName, false);   
  5. }   
  6.   
  7. protected string ReadProperty(ref string field,    
  8.     string propertyName, bool forceRead)   
  9. {   
  10.     if (string.IsNullOrEmpty(field))   
  11.         lock (this)   
  12.             if (string.IsNullOrEmpty(field))   
  13.             {   
  14.                 if (forceRead)   
  15.                     field = properties.ConfigPoint.Attributes[propertyName];   
  16.                 else field = Properties.ConfigPoint.GetAttribute(propertyName);   
  17.             }   
  18.     return field;   
  19. }  

再来看看如何获取到MathOne插件:IMath mathOne = FindAddinItem<IMath>(MathOneKey);

由于我们已经可以读取MathOne的完全路径,所以就可以很轻松通过上面的方式的取出MathOne。如果指定的插件项目路径有误或是插件项目不存在,上面的FindAddIntem<T>方法就会抛出NoFoundAddinItemException的异常。

接下来再看看主程序及插件配置文件的代码: 

主程序的代码(程序集:Unit.Loader.dll)
  1. using System;   
  2. using Mussel;   
  3.   
  4. namespace Unit   
  5. {   
  6.     class Program   
  7.     {   
  8.         static void Main()   
  9.         {   
  10.             MusselService service = new MusselService();   
  11.             service.Start();   
  12.   
  13.             IMath mathOne = 
  14.               service.Container["/Core/Services,MathOne"as IMath;   
  15.   
  16.             if (mathOne != null) mathOne.Calculate(100, 150);   
  17.   
  18.   
  19.             Console.WriteLine();   
  20.   
  21.             IMath mathTwo =   
  22.                 service.Container["/Core/Services,MathTwo"as IMath;   
  23.   
  24.             if (mathTwo != null) mathTwo.Calculate(100, 150);   
  25.   
  26.             Console.ReadLine();   
  27.   
  28.             service.Dispose();   
  29.         }   
  30.     }   
  31. }  

 

插件配置文件(Core.addin)
  1. <?xml version="1.0" encoding="utf-8" ?>  
  2. <Addin Name="Core">  
  3.   <ReferenceAssemblies>  
  4.     <Reference AssemblyFile="Unit.MathOne.dll"    
  5.                IsMusselAssembly="true"/>  
  6.     <Reference AssemblyFile="Unit.MathTwo.dll"    
  7.                IsMusselAssembly="true"/>  
  8.   </ReferenceAssemblies>  
  9.   <AddinNode Path="/Core/Services">  
  10.     <AddinItem ClassKey="MathOne"/>  
  11.     <AddinItem ClassKey="MathTwo"    
  12.                MathOne="/Core/Services,MathOne"/>  
  13.   </AddinNode>  
  14. </Addin>  

可以看到,主程序的代码与上篇中的基本上没有什么差异,有变动的插件配置文件。由于我们在MathTwo中需要从配置文件中读取相应节点的的附加特性(MathOne特性),所以<AddinItem ClassKey="MathTwo" MathOne="/Core/Services,MathOne"/>在这个位置多出了一个插件的自定义特性。

运行结果:

点击下载程序源文件