在.Net项目中,有时候我们需要开发并部署多个WCF服务模块,而且希望WCF服务能和各个网站更好的沟通,必要时还需要作相应的安全验证等等,这里所以要介绍的就是满足这些需求的WCF模块框架,使用此框架只需要引用KudySharp类库。
当接收到客户端发出的请求后,首先会验证所请求的模块令牌(token)(下面会介绍),然后执行模块主机的自定义通道验证(所有模块请求都会执行),最先执行所请求的模块的自定义通道验证,如果全部验证都通过了,执行被调用接口并返回到客户端。
另外,此框架还支持WCF路由,就是说,部署在多部服务器上,把其中一台服务器作为请求的入口来调用其它服务器上的模块服务。路由可以是多重的,如上图所示。
下面介绍使用它必须要了解的4个类成员:
模块主机基类(ModuleHost),上面图解中的Token验证和ModuleHost验证就是在此类中实现的(VerifyChannel),需要开发的模块返回的Token也是由它产生的。
public class ModuleHost : MarshalByRefObject, IChannelVerifier, IModuleHost
{
// 生成模块令牌
public virtual string GenerateToken(string tokenSalt, string serviceName);
// 验证模块令牌
public virtual bool VerifyToken(string token, string serviceName);
// 自定义通道验证(所有模块请求,此方法都会先被执行)
public virtual VerifyChannelResult VerifyChannel(ChannelContext channelContext);
// 其它成员....
}
模块基类(ModuleBase),上面图解中的Module验证就是在此类中实现的(VerifyChannel),Token值由上面的模块主机类产生。
public abstract class ModuleBase<TModule, TContract, TService> : IChannelVerifier, IModule
where TModule : ModuleBase<TModule, TContract, TService>, new()
where TService : TContract, new()
{
// 模块令牌
public abstract string Token { get; }
// 模块被加载后执行
public virtual void OnLoad();
// 模块被卸载后执行
public virtual void OnUnload();
// 模块内部的自定义通道验证(此模块请求时,此方法才会被执行)
public virtual VerifyChannelResult VerifyChannel(ChannelContext channelContext);
// 其它成员....
}
通道上下文类(ChannelContext),用于客户端与服务器端的附加信息传递。
[Serializable]
public sealed class ChannelContext : MarshalByRefObject, ILogicalThreadAffinative
{
// 当前通道上下文实例
public static ChannelContext Current { get; set; }
// 上下文数据
public Dictionary<string, object> ContextData { get; }
// 通过键值访问或设置上下文数据
public object this[string key] { get; set; }
// 时区(需要处理国际化时间时才可能用得上)
public TimeZoneInfo TimeZone { get; set; }
// 返回信息(一般情况下客户端需要得到服务端的返回信息,需要额外的信息,可以通过ContextData或键值索引来设置)
public string ReturnMessage { get; set; }
// 两个基于 TimeZone 属性转换时间的方法
public static DateTime ConvertTimeFromUtc(DateTime dateTime);
public static DateTime ConvertTimeToUtc(DateTime dateTime);
// 获取当前服务端口
public static int GetCurrentServicePort();
// 获取当前服务名称
public static string GetCurrentServiceName();
// 获取最先请求的客户端IP地址
public static string GetCurrentRemoteEndpointAddress();
// 获取请求的客户端IP地址(在启用路由的情况下,可指定原始请求的还是直接请求的客户端)
public static string GetCurrentRemoteEndpointAddress(bool original);
}
模块客户端类(ModuleClient),这个类是给客户端调用模块服务接口的工具类。
public static class ModuleClient
{
// 创建通道,没返回值
public static void CreateChannel<TModule, TChannel>(string server, int port, Action<TChannel> action);
// 创建通道,有返回值TResult
public static TResult CreateChannel<TModule, TChannel, TResult>(string server, int port, Func<TChannel, TResult> action);
// 创建通道并启用路由,没返回值
public static void CreateChannel<TModule, TChannel>(string server, int port, Action<TChannel> action, params string[] routingServers);
// 创建通道并启用路由,有返回值TResult
public static TResult CreateChannel<TModule, TChannel, TResult>(string server, int port, Func<TChannel, TResult> action, params string[] routingServers);
}
有了上面的重要成员介绍,要基于它开发WCF服务就不难了,然而,这只是一个基本的框架,要管理WCF服务还是需要写一些额外的代码的,为了方便使用,本人另外写了个基于这框架的WCF模块服务托管程序MSH(Module Service Hosting),有关它的介绍与开发实例请看这篇文章:
基于KudySharp 中的 ModuleFramework(模块框架)的ModuleServiceHosting(MSH)WCF模块服务托管程序介绍与开发实例