利用Castle IOC实现远程调用的接口统一(上)
摘要:前段时间学习了解了一下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 编译运行成功
本文原创,不允许转贴。