利用Castle IOC实现远程调用的接口统一(上)

摘要:前段时间学习了解了一下Castle,也想着写点东西。只是不知道写些什么东西好,再加上本人的文采实在是不敢恭维,所以就一直没动手写。这两天本着学习的态度写了一个Castle的Facility。不管代码有没有用,希望对您学习Castle能有一定的帮助。

主要内容
            1、功能概述

            2、如何实现服务器端

            3、如何实现客户端

            4、功能组件实现

            5、代码下载

            6、其他说明

一.功能概述

         该Facility主要功能是收集添加到Windsor组件中的本允许远程调用的方法,然后利用反射,在内部实现一个接口,通过该接口来调用这些公开的方法。也就是说对于客户端,只需要这个接口来调用服务器上的其他接口。由于只有一个调用接口,我们就可以很容易的通过简单的配置来选择不同的调用机制,比如通过Remoting,通过命名管道(NamedPipe)。本文章主要介绍如何应用该Facility.

二.如何实现服务器端

          服务器端代码很简单,只需要一行代码。

               IWindsorContainer container  =   new  WindsorContainer( new  XmlInterpreter());
         指示需要通过App.config 或 web.config来读取配置文件。

         服务器端配置是通过App.config 或 web.config来包含Windsor的配置文件, 配置也很简单。配置信息如下:
     
None.gif <? xml version = " 1.0 "  encoding = " utf-8 "   ?>
None.gif    
< configuration >
None.gif    
None.gif        
< configSections >
None.gif            
< section name = " castle "  type = " Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor "   />
None.gif        
</ configSections >
None.gif    
None.gif        
< castle >
None.gif            
< include uri = " file://Castle.NamedPipe.xml "   />
None.gif            
<!--< include uri = " file://Castle.Remoting.xml "   />-->
None.gif            
< include uri = " file://Castle.Components.xml "   />
None.gif        
</ castle >
None.gif    
None.gif    
</ configuration >
None.gif

            上面的配置是通过命名管道调用机制来提供接口,如果希望通过Remoting调用机制,只需要简单的修改一下该配置。当然也需要修改客户端的配置文件,下面会提到。 我们再看看Castle.NamedPipe.xml 文件的配置信息。
            
None.gif < configuration >
None.gif    
None.gif            
< facilities >
None.gif            
None.gif                
< facility id = " actionRemoting "  type = " Suren.Module.ActionMarshal.Manager.Facility.RemotingActionFacility,Suren.Module.ActionMarshal.Manager " ></ facility >
None.gif                
None.gif            
</ facilities >
None.gif            
< components >
None.gif        
None.gif                
< component id = " service "  
None.gif                    service
= " Suren.Module.ActionMarshal.Core.IMarshalService, Suren.Module.ActionMarshal.Core "
None.gif                    type
= " Suren.Module.ActionMarshal.Manager.Service.NamedPipe.NamedPipeService, Suren.Module.ActionMarshal.Manager " >
None.gif                    
< parameters >
None.gif                        
< name > MarshalRemotingTest </ name >     
None.gif                    
</ parameters >
None.gif                
</ component >
None.gif            
</ components >
None.gif        
None.gif        
</ configuration >
None.gif

            该配置文件配置了一个自定义的Facility。用来收集组件中的接口方法。还配置了一个实现命名管道服务组件。有关该自定义的Facility与服务组件的详细信息,可以看源代码。 如果大家有需要会写写下半部分,介绍一下该Facility 的代码。
               以下是Castle.Remoting.xml 文件的配置信息
None.gif < configuration >
None.gif
None.gif        
< facilities >
None.gif        
None.gif            
< facility 
None.gif                id
= " remote.facility "  
None.gif                type
= " Castle.Facilities.Remoting.RemotingFacility, Castle.MicroKernel "
None.gif                isServer
= " true "
None.gif                registryUri
= " kernel.rem "
None.gif                remotingConfigurationFile
= " RemotingTcpConfig.config " >
None.gif            
</ facility >     
None.gif            
None.gif            
< facility id = " actionRemoting "  type = " Suren.Module.ActionMarshal.Manager.Facility.RemotingActionFacility,Suren.Module.ActionMarshal.Manager " ></ facility >
None.gif            
None.gif        
</ facilities >
None.gif        
< components >
None.gif            
None.gif            
< component id = " service "  
None.gif                service
= " Suren.Module.ActionMarshal.Core.IMarshalService, Suren.Module.ActionMarshal.Core "
None.gif                type
= " Suren.Module.ActionMarshal.Manager.Service.Remoting.RemotingService, Suren.Module.ActionMarshal.Manager "
None.gif                remoteserver
= " component "   />
None.gif        
</ components >
None.gif    
None.gif    
</ configuration >

三.如何实现客户端

          客户端的配置与服务器配置比较相似。也是通过App.config或Web.config来包含其它配置文件。配置如下:

None.gif <? xml version = " 1.0 "  encoding = " utf-8 "   ?>
None.gif        
< configuration >
None.gif        
None.gif            
< configSections >
None.gif                
< section name = " castle "  type = " Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor "   />
None.gif            
</ configSections >
None.gif        
None.gif            
< castle >
None.gif                 
< include uri = " file://client_NamedPipe.xml "   />
None.gif                
<!--< include uri = " file://client_Remoting.xml "   />-->
None.gif            
</ castle >
None.gif        
None.gif        
</ configuration >

         上面是的配置是通过命名管道来调用服务器接口,如果希望通过Remoting调用机制,只需要简单的修改一下该配置。当然也需要修改服务器端的配置文件。 我们再看看Castle.NamedPipe.xml 文件的配置信息。
None.gif <? xml version = " 1.0 "  encoding = " utf-8 "   ?>  
None.gif        
< configuration >
None.gif          
None.gif          
< components >
None.gif          
None.gif                
< component id = " service "  
None.gif                    service
= " Suren.Module.ActionMarshal.Core.IMarshalService, Suren.Module.ActionMarshal.Core "
None.gif                    type
= " Suren.Module.ActionMarshal.Client.NamedPipeClient, Suren.Module.ActionMarshal.Client " >
None.gif                    
< parameters >
None.gif                        
< pipeName > MarshalRemotingTest </ pipeName >
None.gif                        
< server > 192.168 . 0.68 </ server >
None.gif                    
</ parameters >
None.gif                
</ component >
None.gif          
</ components >
None.gif        
None.gif        
</ configuration >
            该配置文件配置了一个实现了命名管道客户端的组件,在配置文件中注入了两个参数,一个是命名管道名称,一个是命名管道服务器地址。命名管道名称必须与服务器上配置的一样。 以下是Client_Remoting.xml的配置信息:
None.gif <? xml version = " 1.0 "  encoding = " utf-8 "   ?>  
None.gif    
< configuration >
None.gif    
None.gif      
< facilities >
None.gif      
None.gif        
< facility 
None.gif            id
= " remote.facility "  
None.gif            type
= " Castle.Facilities.Remoting.RemotingFacility, Castle.MicroKernel "
None.gif            remotingConfigurationFile
= " RemotingTcpConfigClient.config "
None.gif            isClient
= " true "
None.gif            remoteKernelUri
= " tcp://localhost:2133/kernel.rem "
None.gif            baseUri
= " tcp://localhost:2133 "   />
None.gif      
None.gif      
</ facilities >
None.gif      
None.gif      
None.gif      
< components >
None.gif      
None.gif            
< component id = " service "  
None.gif                service
= " Suren.Module.ActionMarshal.Core.IMarshalService, Suren.Module.ActionMarshal.Core "
None.gif                type
= " Suren.Module.ActionMarshal.Manager.Service.Remoting.RemotingService, Suren.Module.ActionMarshal.Manager "
None.gif                remoteclient
= " component "   />
None.gif      
</ components >
None.gif    
None.gif    
</ configuration >     
           
          客户端的调用代码如下:
None.gif IWindsorContainer container  =   new  WindsorContainer( new  XmlInterpreter());
None.gif    IMarshalService service 
=  container[ " service " as  IMarshalService;
None.gif    
object  ret  =  service.Execute( " Sum3 " , 100 , 200 , 300 );
None.gif    Console.WriteLine(ret);
            第三行代码作用是执行标识为Sum3的函数,该函数有三个参数,传递该函数的参数分别为100,200,300.执行完成后返回调用结果。

四.组件实现 
          我们先看看一个简单的组件实现。
None.gif namespace  Test.Components
ExpandedBlockStart.gifContractedBlock.gif    
dot.gif {
InBlock.gif        
using System;
InBlock.gif        
using Suren.Module.ActionMarshal.Core;
InBlock.gif        
InBlock.gif        [Marshal]
InBlock.gif        
public class CalcServiceImpl : MarshalByRefObject, ICalcService
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
public CalcServiceImpl()
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
ExpandedSubBlockEnd.gif            }

InBlock.gif            
public int Sum(params int[] args)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
int sum = 0;
InBlock.gif    
InBlock.gif                
foreach(int arg in args)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    sum 
+= arg;
ExpandedSubBlockEnd.gif                }

InBlock.gif                
return sum;
ExpandedSubBlockEnd.gif            }

InBlock.gif            [Marshal(
"Sub")]
InBlock.gif            
public int Sum(int arg)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
int sum;
InBlock.gif                sum 
= arg;
InBlock.gif                
return sum;
ExpandedSubBlockEnd.gif            }

InBlock.gif    
InBlock.gif            [Marshal(
"Sum3",MarshalName="对三个整数的相加")]
InBlock.gif            
public int Sum(int i1 ,int i2,int i3)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
int sum ;
InBlock.gif                sum 
= i1 + i2 + i3;
InBlock.gif                
return sum;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif        
ExpandedBlockEnd.gif    }
            该类上定义了MarshalAttribute属性。表示该类中的所有公共方法都允许远程调用。我们还可以在方法上也定义MarshalAttribute来修改默认的方法信息。
 
           用默认信息标识对外接口,即用方法名称(Sum)作为该对外接口的标识。
None.gif public   int  Sum( params   int [] args)
ExpandedBlockStart.gifContractedBlock.gif        
dot.gif {
InBlock.gif            
int sum = 0;
InBlock.gif    
InBlock.gif            
foreach(int arg in args)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                sum 
+= arg;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
return sum;
ExpandedBlockEnd.gif        }

            用Sub作为该对外接口的标识
None.gif [Marshal( " Sub " )]
None.gif        
public   int  Sum( int  arg)
ExpandedBlockStart.gifContractedBlock.gif        
dot.gif {
InBlock.gif            
int sum;
InBlock.gif            sum 
= arg;
InBlock.gif            
return sum;
ExpandedBlockEnd.gif        }

            用Sum3作为该对外接口的标识,并设置该接口的描述说明
None.gif [Marshal( " Sum3 " ,MarshalName = " 对三个整数的相加 " )]
None.gif        
public   int  Sum( int  i1 , int  i2, int  i3)
ExpandedBlockStart.gifContractedBlock.gif        
dot.gif {
InBlock.gif            
int sum ;
InBlock.gif            sum 
= i1 + i2 + i3;
InBlock.gif            
return sum;
ExpandedBlockEnd.gif        }

None.gif        

         如果我们没有在类上定义[Marshal],只在某些公共方法上定义Marshal属性。则只公开定义了Marshal属性的这些方法。
通常情况下我们把标识作为功能号。如[Marshal("10000")]  [Marshal("10001")] [Marshal("10002")] 
         调用的时候int ret = (int)service.Execute("10001",100,200,300);
         值得注意的是所有的标识号不能重复.

         在服务器上配置组件 Castle.Components.xml

None.gif < configuration >
None.gif        
< components >
None.gif    
None.gif            
< component id = " calcservice "  
None.gif                service
= " Test.Components.ICalcService,Test.Components "  
None.gif                type
= " Test.Components.CalcServiceImpl,Test.Components " >
None.gif            
</ component >
None.gif            
< component id = " serviceOne "  
None.gif                service
= " Test.Components.IServiceOne,Test.Components "  
None.gif                type
= " Test.Components.ServiceOneImpl,Test.Components " >
None.gif            
</ component >
None.gif        
</ components >
None.gif        
None.gif    
</ configuration >

在客户端上不需要作任何配置。也不需要引用这些组件
  
五.代码下载
 
       所有源代码  下载
 
 
六.其他说明

 命名管道实现代码 http://www.codeproject.com/csharp/dotnetnamedpipespart2.asp

 环境:windows 2003 \ Visual Studio 2003 \ framework1.1 编译运行成功
 
 本文原创,不允许转贴。

转载于:https://www.cnblogs.com/SurenSuyu/archive/2006/09/26/515014.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值