利用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的配置文件, 配置也很简单。配置信息如下:
     
<? xml version = " 1.0 "  encoding = " utf-8 "   ?>
    
< configuration >
    
        
< configSections >
            
< section name = " castle "  type = " Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor "   />
        
</ configSections >
    
        
< castle >
            
< include uri = " file://Castle.NamedPipe.xml "   />
            
<!--< include uri = " file://Castle.Remoting.xml "   />-->
            
< include uri = " file://Castle.Components.xml "   />
        
</ castle >
    
    
</ configuration >

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

            该配置文件配置了一个自定义的Facility。用来收集组件中的接口方法。还配置了一个实现命名管道服务组件。有关该自定义的Facility与服务组件的详细信息,可以看源代码。 如果大家有需要会写写下半部分,介绍一下该Facility 的代码。
               以下是Castle.Remoting.xml 文件的配置信息
< configuration >

        
< facilities >
        
            
< facility 
                id
= " remote.facility "  
                type
= " Castle.Facilities.Remoting.RemotingFacility, Castle.MicroKernel "
                isServer
= " true "
                registryUri
= " kernel.rem "
                remotingConfigurationFile
= " RemotingTcpConfig.config " >
            
</ facility >     
            
            
< facility id = " actionRemoting "  type = " Suren.Module.ActionMarshal.Manager.Facility.RemotingActionFacility,Suren.Module.ActionMarshal.Manager " ></ facility >
            
        
</ facilities >
        
< components >
            
            
< component id = " service "  
                service
= " Suren.Module.ActionMarshal.Core.IMarshalService, Suren.Module.ActionMarshal.Core "
                type
= " Suren.Module.ActionMarshal.Manager.Service.Remoting.RemotingService, Suren.Module.ActionMarshal.Manager "
                remoteserver
= " component "   />
        
</ components >
    
    
</ configuration >

三.如何实现客户端

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

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

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

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

            
public int Sum(params int[] args)
            
{
                
int sum = 0;
    
                
foreach(int arg in args)
                
{
                    sum 
+= arg;
                }

                
return sum;
            }

            [Marshal(
"Sub")]
            
public int Sum(int arg)
            
{
                
int sum;
                sum 
= arg;
                
return sum;
            }

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

        }

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

            
return sum;
        }

            用Sub作为该对外接口的标识
[Marshal( " Sub " )]
        
public   int  Sum( int  arg)
        
{
            
int sum;
            sum 
= arg;
            
return sum;
        }

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

        

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

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

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

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

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

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

你可能感兴趣的:(cast)