摘要:前段时间学习了解了一下Castle,也想着写点东西。只是不知道写些什么东西好,再加上本人的文采实在是不敢恭维,所以就一直没动手写。这两天本着学习的态度写了一个Castle的Facility。不管代码有没有用,希望对您学习Castle能有一定的帮助。
主要内容
1、功能概述
2、如何实现服务器端
3、如何实现客户端
4、功能组件实现
5、代码下载
6、其他说明
一.功能概述
该Facility主要功能是收集添加到Windsor组件中的本允许远程调用的方法,然后利用反射,在内部实现一个接口,通过该接口来调用这些公开的方法。也就是说对于客户端,只需要这个接口来调用服务器上的其他接口。由于只有一个调用接口,我们就可以很容易的通过简单的配置来选择不同的调用机制,比如通过Remoting,通过命名管道(NamedPipe)。本文章主要介绍如何应用该Facility.
二.如何实现服务器端
服务器端代码很简单,只需要一行代码。
服务器端配置是通过App.config 或 web.config来包含Windsor的配置文件, 配置也很简单。配置信息如下:
< 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 文件的配置信息。
< 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 文件的配置信息
< 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来包含其它配置文件。配置如下:
< 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 文件的配置信息。
< 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 >
< 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 >
客户端的调用代码如下:
IMarshalService service = container[ " service " ] as IMarshalService;
object ret = service.Execute( " Sum3 " , 100 , 200 , 300 );
Console.WriteLine(ret);
四.组件实现
我们先看看一个简单的组件实现。
{
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;
}
}
}
用默认信息标识对外接口,即用方法名称(Sum)作为该对外接口的标识。
{
int sum = 0;
foreach(int arg in args)
{
sum += arg;
}
return sum;
}
用Sub作为该对外接口的标识
public int Sum( int arg)
{
int sum;
sum = arg;
return sum;
}
用Sum3作为该对外接口的标识,并设置该接口的描述说明
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
< 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 编译运行成功
本文原创,不允许转贴。