不是架构的架构之四:业务层的实现与自动代理

我们在开篇中提到,希望能有一种办法,能自动适应系统的环境配置,在局域网小型应用中将直接访问数据库以获得最高的性能,在分布式环境中自动使用WCF来获得较好的安全性和连通性。

但是,我们不希望这样的特性使我们的开发变得过于复杂,需要在新特性和工作量之间寻求一个合理的平衡点。

 


 

原理分析:

用自动代理的业务层结构如下:

image

检测到局域网配置时的情况,将直接返回业务对象实例。

image

分布式配置的调用情况。

我们可以从图上看出,使用局域网配置或分布式配置完全取决于自动代理对象,而对于使用者(表现层)是完全透明的。当然,对于分布式配置的情况,传入业务端的参数和结果都是需要经过序列化的,否则将无法在WCF中传输,这是我们在开发业务层时需要注意的问题。

自动代理的对象实现很简单,我们需要做的就是拦截调用,将调用的信息(业务对象名,方法名,参数)等构建为WCF服务对象的参数,通过统一的服务接口调用服务端,服务端得到调用后,根据调用信息实例化合适的业务对象,调用相应的方法,完成后将结果以统一的返回格式返回给自动代理对象,而这些返回的数据将被反序列化后作为该方法的返回值。


代码实现:

在目前的开源框架中,Castle和Spring.net都提供了很好的自动代理的类库。我们将以Spring.net为例来实现自动代理对象。

public static class BizAutoWcfProxy
{public static T Get<T>(T instance) where T : class{var p = new ProxyFactory(instance);p.AddAdvice(new AroundAdvise());return p.GetProxy() as T;}internal static IWcfProxy GetMethodProxy(){var service = PubFunc.GetAppSetting("WcfService");if (string.IsNullOrEmpty(service)){return new WcfProxy();}var binding = new NetTcpBinding(SecurityMode.None, false);var f = new ChannelFactory<IWcfProxy>(binding, service);var proxy = f.CreateChannel();return proxy;}
}

上面是自动代理工厂的实现.这个工厂中,提供了一个供自动代理对象使用的方法GetMethodProxy,这个方法中检测应用程序配置文件的WcfService配置,如果配置不为空,则创建自动代理对象,否则直接返回.

 

public class AroundAdvise : IMethodInterceptor
{public object Invoke(IMethodInvocation invocation){Log.Get().Debug("方法{0}被调用被拦截", invocation.Method.Name);try{var p = BizAutoWcfProxy.GetMethodProxy();//调用信息var m = new MethodProxy{ClassName = invocation.TargetType.AssemblyQualifiedName,        //业务对象名MethodName = invocation.Method.Name                             //方法};//将调用参数也包含在调用信息中if (invocation.Arguments != null && invocation.Arguments.Length > 0)m.Params = invocation.Arguments.ToList().ConvertAll(PubFunc.Serialize.ObjToBytes).ToArray();//调用WCF服务var r = p.Execute(m);//正常的情况,没有异常出现if (!r.HasException){//返回值object returnValue = r.GetValue();var ind = 0;//处理ref和out的参数的返回invocation.Method.GetParameters().ToList().ForEach(mp =>{if (mp.IsOut){invocation.Arguments[mp.Position] = PubFunc.Serialize.BytesToObj(r.OutValue[ind++]);}});return returnValue;}//出现异常的情况,反序列号异常信息,重新在客户端抛出var ex = PubFunc.Serialize.BytesToObj(r.Exception) as Exception;if (ex != null) throw ex;throw new Exception("无法反序列化异常信息");}catch (CommunicationException oe){Log.Get().Debug("WCF通讯错误", oe);throw;}}
}

 

上面是方法拦截的实现。这里除了需要考虑正常情况下调用之外,还要考虑服务器端可能发生的异常,这里增加了对异常的处理。

//唯一的WCF接口
[ServiceContract]
public interface IWcfProxy
{[OperationContract]ReturnValue Execute(MethodProxy m);
}
//服务实现
public class WcfProxy : IWcfProxy
{public ReturnValue Execute(MethodProxy m){try{//服务端实例化业务对象var con = Type.GetType(m.ClassName).GetConstructor(BindingFlags.NonPublic| BindingFlags.Public| BindingFlags.Instance,null,new Type[0],null);var cls = con.Invoke(new object[0]);//处理参数的反序列化var method = cls.GetType().GetMethod(m.MethodName, BindingFlags.Instance | BindingFlags.Public);var pm = new object[0];if (m.Params != null && m.Params.Length > 0)pm = m.Params.ToList().ConvertAll(PubFunc.Serialize.BytesToObj).ToArray();//调用var rlt = method.Invoke(cls, pm);var r = new ReturnValue();r.SetValue(rlt);//处理out参数var outPlist = new List<byte[]>();method.GetParameters().ToList().ForEach(p =>{if(p.IsOut){outPlist.Add(PubFunc.Serialize.ObjToBytes(pm[p.Position]));}});if (outPlist.Count > 0)r.OutValue = outPlist.ToArray();//正常返回return r;}catch(TargetInvocationException ex1){var ex = ex1.InnerException;//处理服务器端发生的两种异常信息,这些属于正常的业务异常,需要返回到客户端if (ex is BizException || ex is DAException){var r = new ReturnValue();r.HasException = true;r.Exception = PubFunc.Serialize.ObjToBytes(ex);return r;}else{//非正常情况下的异常,统一包装为服务端异常返回var serverex = new ServerException(ex.Message);serverex.Trace = ex.StackTrace;var r = new ReturnValue();r.HasException = true;r.Exception = PubFunc.Serialize.ObjToBytes(serverex);return r;}}}
}
//服务返回对象
[DataContract]
public class ReturnValue
{[DataMember]public bool HasException { get; set; }[DataMember]public byte[] Exception { get; set; }[DataMember]public byte[] Value { get; set; }[DataMember]public byte[][] OutValue { get; set; }public void SetValue(object value){if (value == null){Value = null; return;}Value=PubFunc.Serialize.ObjToBytes(value);}public object GetValue(){if (Value == null){return null;}return PubFunc.Serialize.BytesToObj(Value);}
}
//调用信息
[DataContract]
public class MethodProxy
{[DataMember]public string ClassName { get; set; }[DataMember]public string MethodName { get; set; }[DataMember]public byte[][] Params{get;set;}
}

这里是完整的服务端的方法,提供WCF接口,处理业务层对象调用的过程。


实现不算复杂,代码也不多,欢迎讨论。不足之处请指正。

转载于:https://www.cnblogs.com/yiway/archive/2011/01/24/MY_FW_4.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/298719.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python程序设计实践教程陈东_Python

“我们正步入一个数据或许比软件更重要的新时代。——Tim OReilly” 运用数据是精准刻画事物、呈现发展规律的主要手段&#xff0c;分析数据展示规律&#xff0c;把思想变得更精细&#xff01; 本课程面向各类编程学习者&#xff0c;讲解利用Python语言表达N维数据并结合数据特…

Silverlight中开发和设计人员的合作文档信息

-----------------------------------------------------------------------------------> copyright:http://www.docin.com/p-34191215.html转载于:https://www.cnblogs.com/molin/archive/2009/12/08/silverlight_manager.html

和男朋友一块儿吃VS单独一人在家吃饭

1 和男朋友一块儿吃VS单独一人在家吃饭2 忍不住要为这位跳高选手鼓掌了3 我们家的蔬菜就没有这种觉悟4 这螳螂拳算是练到家了5 现实中的你胖的一批 6 这套户型咋样&#xff1f;7 你能看出几个字你点的每个赞&#xff0c;我都认真当成了喜欢

指针04 - 零基础入门学习C语言44

第八章&#xff1a;指针04 让编程改变世界 Change the world by program 小结 归纳起来, 如果有一个实参数组, 想在函数中改变此数组中的元素的值, 实参与形参的对应关系有以下&#xff14;种情况&#xff1a; (1) 形参和实参都用数组名, 如&#xff1a; [codesyntax lang&…

填坑 | .NET 5在Docker中访问MSSQL报错

【.NET Core】| 作者 / Edison Zhou不知道你有没有在.NET Core/.NET 5的Docker访问MS SQL Server数据库&#xff0c;如果有&#xff0c;那么很有可能会遇到这个错误。1SSL版本错误最近在公司用.NET 5重构部分业务服务&#xff0c;由于之前老系统使用了MS SQL Server数据库&…

六个机械原理,动图形象直观、解读通俗易懂

全世界只有3.14 % 的人关注了爆炸吧知识01间歇运动机构▼间歇运动机构能够将原动件的连续转动转变为从动件周期性运动和停歇的机构&#xff0c;称为间歇运动机构。例如牛头刨床工作台的横向进给运动&#xff0c;电影放映机的送片运动等都用有间歇运动机构。常见的间歇运动机构有…

linux读写usb host,LINUX下USB1.1设备学习小记(3)_host与device

各位还记得”任何传输都是由host发起的”这句话么~在usb设备插入pc中到拔出usb设备,都是由host进行询问的一个usb鼠标的工作流程可以表达如下:usb鼠标插入pc中:主机询问设备:给我你的设备信息(控制传输)主机根据usb鼠标的设备信息进行驱动配置,配置结束后主机询问设备:给我你的…

java判断时间区间 隔天_Java初中级程序员面试题宝典

Java基础部分&与&&区别&#xff1f;&和&&都是逻辑运算符&#xff0c;都是判断两边同时真则为真&#xff0c;否则为假&#xff1b;但是&&当第一个条件不成之后&#xff0c;后面的条件都不执行了&#xff0c;而&则还是继续执行&#xff0c;直…

什么是sns

SNS 目录[隐藏] 第一章 什么是SNS&#xff1f; 第二章 SNS带给顾客的特殊价值描绘 第三章 观察SNS的技术与服务 第四章 SNS市场与竞争 第五章 SNS的主要营销策略简介 第六章 中国SNS的发展与主要网站及产品SNSSNS&#xff0c;全称Social Networking Services&#xff0c;即社会…

elsa-core——1.Hello World:Console

github上有一个开源的工作流项目elsa&#xff0c;elsa-core是core语言的版本&#xff0c;其文档因为是英文&#xff0c;因此会让很多人不想看&#xff0c;或者是看不下去&#xff0c;从这篇文章开始我将开始对elsa-core的文档翻译成中文并分享出来&#xff0c;方便大家查看与学…

docker 查看容器_Docker介绍

docker介绍什么是docker&#xff1f;我们先看一下官方文档对docker的定义。翻译一下就是&#xff1a;Docker是一个集开发&#xff0c;发布和运行应用程序的开放平台。Docker能够分离应用和基础架构&#xff0c;从而可以使得用户可以快速交付软件。借助于Docker&#xff0c;用户…

ASF经验谈(上)

http://software.intel.com/zh-cn/blogs/2009/12/01/asf/?cidsw:51cto【前言】写这篇文章之前先声明一下&#xff0c;笔者这里说到的ASF不是指Microsoft的多媒体文件的ASF格式&#xff08;可能这个很多人更熟悉一些&#xff09;&#xff0c;而是用于远程管理的ASF(Alert Stand…

ubuntu linux 批量部署,使用Cobbler批量部署Linux和Windows:CentOS/Ubuntu批量安装(二)...

通过前面服务端的部署&#xff0c;已经配置好了 Cobbler Server 端&#xff0c;接下来开始进行 CentOS/Ubuntu 的批量安装&#xff0c;在进行 CentOS/Ubuntu 批量安装时&#xff0c;也需要通过Cobbler来做相应的发行版导入配置。流程如下&#xff1a;上传ISO镜像到 Cobbler Ser…

盘点这些年被黑的最惨的语言

全世界只有3.14 % 的人关注了爆炸吧知识这些年&#xff0c;被黑过的语言数不胜数&#xff0c;最惨的要数HTML&#xff0c;但CSS、Python等也惨遭黑手比惨&#xff1f;这就来一波。HTMLHTMLC语言C语言JavaJavaJavaJavaJavaScript JavaScript JavaScriptJavaPHPPHPPHPPHPPythonPy…

2011目标 及 总结

20110918 添加 Glodon 任务规划 20110612 修改 经过年中分析&#xff0c;把下半年目标定为&#xff1a; 重心转向技术开发&#xff0c;有闲暇的时间就继续完成年初计划中的其它项。在技术学习方面&#xff0c;注意&#xff1a;不要花太多时间在开发“小系统”上&#xff0c;也不…

python 批量下载网页图片_Python实现多线程批量下载图片

《派森》(Python)3.13 win32 英文安装版 类型&#xff1a;编程工具大小&#xff1a;21M语言&#xff1a;英文 评分&#xff1a;8.7 标签&#xff1a; 立即下载 爬取图片可真的是一个可遇不可求的机会。 有需求就会动力。 目标&#xff1a;爬取某个网站上n多页的链接&#xff0c…

linux中获取redis的map,深入Redis之 bitmap位图和HyperLogLog(五)

bitmap位图我们知道一个字符占1个字节&#xff0c;也就是8个位例如set name bigbig字符串中的3个字符的ASCII码为98 105 113所以big转为二进制就是&#xff1a;01100010|01101001|01100111b i g占了3个字节的大小&#xff0c;一共24个位。bitmap位图可以帮我们获取…

想象中的同居生活 VS 真实的同居生活

1 长颈鹿是怎么喝水的2 为了防止雨伞被偷设计师还是真动了不少脑筋呢-3 睡在这样的床上&#xff0c;晒着太阳&#xff0c;肯定超赞4 如何阻止猫咪上楼5 想象中的同居生活 VS 真实的同居生活 6 硬生生把苹果削成吃不饱也吃不起的样子7 来来来准备瓜子杏仁你点的每个赞&#xff…

抽丝剥茧!Source Generators原理讲解

前言前段时间&#xff0c;我们已经用Source Generators实现了好多功能&#xff0c;比如AutoMapper、API最佳实践。你看完那些实现代码&#xff0c;是不是还有点云里雾里&#xff01;Source Generators到底是怎么做到的&#xff1f;基础知识Source Generators是编译过程的一部分…

GPON技术概述

GPON技术转载自《电子发烧友》。文章链接请见&#xff1a;http://www.elecfans.com/article/88/171/2009/2009050556028.htmlGPON技术详述介绍GPON 技术之前&#xff0c;先介绍目前也被应用的另一种PON 技术“EPON”。1&#xff0e;EPON技术介绍EPON 又名 GEPON&#xff0c;是由…