我的编程空间,编程开发者的网络收藏夹
学习永远不晚

如何在WCF中使用动态代理

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

如何在WCF中使用动态代理

这篇文章主要介绍“如何在WCF中使用动态代理”,在日常操作中,相信很多人在如何在WCF中使用动态代理问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”如何在WCF中使用动态代理”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

一、重构前的项目代码

    重构前的项目代码共7层代码,其中WCF服务端3层,WCF接口层1层,客户端3层,共7层

    1.服务端WCF服务层SunCreate.InfoPlatform.Server.Service

    2.服务端数据库访问接口层SunCreate.InfoPlatform.Server.Bussiness

    3.服务端数据库访问实现层SunCreate.InfoPlatform.Server.Bussiness.Impl

    4.WCF接口层SunCreate.InfoPlatform.Contract

    5.客户端代理层SunCreate.InfoPlatform.Client.Proxy

    6.客户端业务接口层SunCreate.InfoPlatform.Client.Bussiness

    7.客户端业务实现层SunCreate.InfoPlatform.Client.Bussiness.Impl

二、客户端通过动态代理重构

    1.实现在拦截器中添加Ticket、处理异常、Close对象

    2.客户端不需要再写代理层代码,而使用动态代理层

    3.对于简单的增删改查业务功能,也不需要再写业务接口层和业务实现层,直接调用动态代理;对于复杂的业务功能以及缓存,才需要写业务接口层和业务实现层

客户端动态代理工厂类ProxyFactory代码(该代码目前写在客户端业务实现层):

using Castle.DynamicProxy;using System;using System.Collections.Concurrent;using System.Collections.Generic;using System.Linq;using System.ServiceModel;using System.Text;using System.Threading.Tasks;namespace SunCreate.InfoPlatform.Client.Bussiness.Imp{ /// <summary> /// WCF服务工厂 /// PF是ProxyFactory的简写 /// </summary> public class PF { /// <summary> /// 拦截器缓存 /// </summary> private static ConcurrentDictionary<Type, IInterceptor> _interceptors = new ConcurrentDictionary<Type, IInterceptor>(); /// <summary> /// 代理对象缓存 /// </summary> private static ConcurrentDictionary<Type, object> _objs = new ConcurrentDictionary<Type, object>(); private static ProxyGenerator _proxyGenerator = new ProxyGenerator(); /// <summary> /// 获取WCF服务 /// </summary> /// <typeparam name="T">WCF接口</typeparam> public static T Get<T>() {  Type interfaceType = typeof(T);  IInterceptor interceptor = _interceptors.GetOrAdd(interfaceType, type =>  {  string serviceName = interfaceType.Name.Substring(1); //服务名称  ChannelFactory<T> channelFactory = new ChannelFactory<T>(serviceName);  return new ProxyInterceptor<T>(channelFactory);  });  return (T)_objs.GetOrAdd(interfaceType, type => _proxyGenerator.CreateInterfaceProxyWithoutTarget(interfaceType, interceptor)); //根据接口类型动态创建代理对象,接口没有实现类 } }}

客户端拦截器类ProxyInterceptor<T>代码(该代码目前写在客户端业务实现层):

using Castle.DynamicProxy;using log4net;using SunCreate.Common.Base;using SunCreate.InfoPlatform.Client.Bussiness;using System;using System.Collections.Generic;using System.Linq;using System.Reflection;using System.ServiceModel;using System.ServiceModel.Channels;using System.Text;using System.Threading.Tasks;namespace SunCreate.InfoPlatform.Client.Bussiness.Imp{ /// <summary> /// 拦截器 /// </summary> /// <typeparam name="T">接口</typeparam> public class ProxyInterceptor<T> : IInterceptor { private static ILog _log = LogManager.GetLogger(typeof(ProxyInterceptor<T>)); private ChannelFactory<T> _channelFactory; public ProxyInterceptor(ChannelFactory<T> channelFactory) {  _channelFactory = channelFactory; } /// <summary> /// 拦截方法 /// </summary> public void Intercept(IInvocation invocation) {  //准备参数  ParameterInfo[] parameterInfoArr = invocation.Method.GetParameters();  object[] valArr = new object[parameterInfoArr.Length];  for (int i = 0; i < parameterInfoArr.Length; i++)  {  valArr[i] = invocation.GetArgumentValue(i);  }  //执行方法  T server = _channelFactory.CreateChannel();  using (OperationContextScope scope = new OperationContextScope(server as IContextChannel))  {  try  {   HI.Get<ISecurityBussiness>().AddTicket();   invocation.ReturnValue = invocation.Method.Invoke(server, valArr);   var value = HI.Get<ISecurityBussiness>().GetValue();   ((IChannel)server).Close();  }  catch (Exception ex)  {   _log.Error("ProxyInterceptor " + typeof(T).Name + " " + invocation.Method.Name + " 异常", ex);   ((IChannel)server).Abort();  }  }  //out和ref参数处理  for (int i = 0; i < parameterInfoArr.Length; i++)  {  ParameterInfo paramInfo = parameterInfoArr[i];  if (paramInfo.IsOut || paramInfo.ParameterType.IsByRef)  {   invocation.SetArgumentValue(i, valArr[i]);  }  } } }}

如何使用:

List<EscortTask> list = PF.Get<IBussDataService>().GetEscortTaskList();

这里不用再写try catch,异常在拦截器中处理

三、WCF服务端通过动态代理,在拦截器中校验Ticket、处理异常

服务端动态代理工厂类ProxyFactory代码(代码中保存动态代理dll不是必需的):

using Autofac;using Castle.DynamicProxy;using Castle.DynamicProxy.Generators;using SunCreate.Common.Base;using System;using System.Collections.Concurrent;using System.Collections.Generic;using System.IO;using System.Linq;using System.Reflection;using System.ServiceModel;using System.ServiceModel.Activation;using System.Text;using System.Threading.Tasks;namespace SunCreate.InfoPlatform.WinService{ /// <summary> /// 动态代理工厂 /// </summary> public class ProxyFactory { /// <summary> /// 拦截器缓存 /// </summary> private static ConcurrentDictionary<Type, IInterceptor> _interceptors = new ConcurrentDictionary<Type, IInterceptor>(); /// <summary> /// 代理对象缓存 /// </summary> private static ConcurrentDictionary<Type, object> _objs = new ConcurrentDictionary<Type, object>(); private static ProxyGenerator _proxyGenerator; private static ModuleScope _scope; private static ProxyGenerationOptions _options; static ProxyFactory() {  AttributesToAvoidReplicating.Add(typeof(ServiceContractAttribute)); //动态代理类不继承接口的ServiceContractAttribute  String path = AppDomain.CurrentDomain.BaseDirectory;  _scope = new ModuleScope(true, false,  ModuleScope.DEFAULT_ASSEMBLY_NAME,  Path.Combine(path, ModuleScope.DEFAULT_FILE_NAME),  "MyDynamicProxy.Proxies",  Path.Combine(path, "MyDymamicProxy.Proxies.dll"));  var builder = new DefaultProxyBuilder(_scope);  _options = new ProxyGenerationOptions();  //给动态代理类添加AspNetCompatibilityRequirementsAttribute属性  PropertyInfo proInfoAspNet = typeof(AspNetCompatibilityRequirementsAttribute).GetProperty("RequirementsMode");  CustomAttributeInfo customAttributeInfo = new CustomAttributeInfo(typeof(AspNetCompatibilityRequirementsAttribute).GetConstructor(new Type[0]), new object[0], new PropertyInfo[] { proInfoAspNet }, new object[] { AspNetCompatibilityRequirementsMode.Allowed });  _options.AdditionalAttributes.Add(customAttributeInfo);  //给动态代理类添加ServiceBehaviorAttribute属性  PropertyInfo proInfoInstanceContextMode = typeof(ServiceBehaviorAttribute).GetProperty("InstanceContextMode");  PropertyInfo proInfoConcurrencyMode = typeof(ServiceBehaviorAttribute).GetProperty("ConcurrencyMode");  customAttributeInfo = new CustomAttributeInfo(typeof(ServiceBehaviorAttribute).GetConstructor(new Type[0]), new object[0], new PropertyInfo[] { proInfoInstanceContextMode, proInfoConcurrencyMode }, new object[] { InstanceContextMode.Single, ConcurrencyMode.Multiple });  _options.AdditionalAttributes.Add(customAttributeInfo);  _proxyGenerator = new ProxyGenerator(builder); } /// <summary> /// 动态创建代理 /// </summary> public static object CreateProxy(Type contractInterfaceType, Type impInterfaceType) {  IInterceptor interceptor = _interceptors.GetOrAdd(impInterfaceType, type =>  {  object _impl = HI.Provider.GetService(impInterfaceType);  return new ProxyInterceptor(_impl);  });  return _objs.GetOrAdd(contractInterfaceType, type => _proxyGenerator.CreateInterfaceProxyWithoutTarget(contractInterfaceType, _options, interceptor)); //根据接口类型动态创建代理对象,接口没有实现类 } /// <summary> /// 保存动态代理dll /// </summary> public static void Save() {  string filePath = Path.Combine(_scope.WeakNamedModuleDirectory, _scope.WeakNamedModuleName);  if (File.Exists(filePath))  {  File.Delete(filePath);  }  _scope.SaveAssembly(false); } }}

说明:object _impl = HI.Provider.GetService(impInterfaceType); 这句代码用于创建数据库访问层对象,HI是项目中的一个工具类,类似Autofac框架的功能

服务端拦截器类ProxyInterceptor<T>代码:

using Castle.DynamicProxy;using log4net;using SunCreate.Common.Base;using SunCreate.InfoPlatform.Server.Bussiness;using System;using System.Collections.Generic;using System.Linq;using System.Reflection;using System.ServiceModel;using System.ServiceModel.Channels;using System.Text;using System.Threading.Tasks;namespace SunCreate.InfoPlatform.WinService{ /// <summary> /// 拦截器 /// </summary> public class ProxyInterceptor : IInterceptor { private static ILog _log = LogManager.GetLogger(typeof(ProxyInterceptor)); private object _impl; public ProxyInterceptor(object impl) {  _impl = impl; } /// <summary> /// 拦截方法 /// </summary> public void Intercept(IInvocation invocation) {  //准备参数  ParameterInfo[] parameterInfoArr = invocation.Method.GetParameters();  object[] valArr = new object[parameterInfoArr.Length];  for (int i = 0; i < parameterInfoArr.Length; i++)  {  valArr[i] = invocation.GetArgumentValue(i);  }  //执行方法  try  {  if (HI.Get<ISecurityImp>().CheckTicket())  {   Type implType = _impl.GetType();   MethodInfo methodInfo = implType.GetMethod(invocation.Method.Name);   invocation.ReturnValue = methodInfo.Invoke(_impl, valArr);  }  }  catch (Exception ex)  {  _log.Error("ProxyInterceptor " + invocation.TargetType.Name + " " + invocation.Method.Name + " 异常", ex);  }  //out和ref参数处理  for (int i = 0; i < parameterInfoArr.Length; i++)  {  ParameterInfo paramInfo = parameterInfoArr[i];  if (paramInfo.IsOut || paramInfo.ParameterType.IsByRef)  {   invocation.SetArgumentValue(i, valArr[i]);  }  } } }}

服务端WCF的ServiceHost工厂类:

using Spring.ServiceModel.Activation;using System;using System.Collections.Generic;using System.Linq;using System.Reflection;using System.ServiceModel;using System.Text;using System.Threading.Tasks;namespace SunCreate.InfoPlatform.WinService{ public class MyServiceHostFactory : ServiceHostFactory { public MyServiceHostFactory() { } public override ServiceHostBase CreateServiceHost(string reference, Uri[] baseAddresses) {  Assembly contractAssembly = Assembly.GetAssembly(typeof(SunCreate.InfoPlatform.Contract.IBaseDataService));  Assembly impAssembly = Assembly.GetAssembly(typeof(SunCreate.InfoPlatform.Server.Bussiness.IBaseDataImp));  Type contractInterfaceType = contractAssembly.GetType("SunCreate.InfoPlatform.Contract.I" + reference);  Type impInterfaceType = impAssembly.GetType("SunCreate.InfoPlatform.Server.Bussiness.I" + reference.Replace("Service", "Imp"));  if (contractInterfaceType != null && impInterfaceType != null)  {  var proxy = ProxyFactory.CreateProxy(contractInterfaceType, impInterfaceType);  ServiceHostBase host = new ServiceHost(proxy, baseAddresses);  return host;  }  else  {  return null;  } } }}

svc文件配置ServiceHost工厂类:

<%@ ServiceHost Language="C#" Debug="true" Service="BaseDataService" Factory="SunCreate.InfoPlatform.WinService.MyServiceHostFactory" %>

如何使用自定义的ServiceHost工厂类启动WCF服务,下面是部分代码:

MyServiceHostFactory factory = new MyServiceHostFactory();List<ServiceHostBase> hostList = new List<ServiceHostBase>();foreach (var oFile in dirInfo.GetFiles()){ try { string strSerName = oFile.Name.Replace(oFile.Extension, ""); string strUrl = string.Format(m_strBaseUrl, m_serverPort, oFile.Name); var host = factory.CreateServiceHost(strSerName, new Uri[] { new Uri(strUrl) }); if (host != null) {  hostList.Add(host); } } catch (Exception ex) { Console.WriteLine("出现异常:" + ex.Message); m_log.ErrorFormat(ex.Message + ex.StackTrace); }}ProxyFactory.Save();foreach (var host in hostList){ try { foreach (var endpoint in host.Description.Endpoints) {  endpoint.EndpointBehaviors.Add(new MyEndPointBehavior()); //用于添加消息拦截器、全局异常拦截器 } host.Open(); m_lsHost.TryAdd(host); } catch (Exception ex) { Console.WriteLine("出现异常:" + ex.Message); m_log.ErrorFormat(ex.Message + ex.StackTrace); }}

WCF服务端再也不用写Service层了 

四、当我需要添加一个WCF接口,以实现一个查询功能,比如查询所有组织机构,重构前,我需要在7层添加代码,然后客户端调用,重构后,我只需要在3层添加代码,然后客户端调用

    1.在WCF接口层添加接口

    2.在服务端数据访问接口层添加接口

    3.在服务端数据访问实现层添加实现方法

    4.客户端调用:var orgList = PF.Get<IBaseDataService>().GetOrgList();

    重构前,需要在7层添加代码,虽然每层代码都差不多,可以复制粘贴,但是复制粘贴也很麻烦啊,重构后省事多了,从此再也不怕写增删改查了

到此,关于“如何在WCF中使用动态代理”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

如何在WCF中使用动态代理

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

如何在WCF中使用动态代理

这篇文章主要介绍“如何在WCF中使用动态代理”,在日常操作中,相信很多人在如何在WCF中使用动态代理问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”如何在WCF中使用动态代理”的疑惑有所帮助!接下来,请跟着小编
2023-06-09

如何使用WCF生成代理

这篇文章主要为大家展示了“如何使用WCF生成代理”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“如何使用WCF生成代理”这篇文章吧。利用WSE(Web Service Enhancements)可
2023-06-17

如何创建使用WCF代理

这篇文章主要为大家展示了“如何创建使用WCF代理”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“如何创建使用WCF代理”这篇文章吧。WCF代理还是比较常用的,于是我研究了一下WCF代理,在这里拿出
2023-06-17

如何在Java中使用Agent动态修改代码

今天就跟大家聊聊有关如何在Java中使用Agent动态修改代码,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。需要两个程序,一个是用来测试的程序,一个agent用于修改代码。1. 测试
2023-05-31

Mapper动态代理如何在Mybatis中实现

Mapper动态代理如何在Mybatis中实现?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。一、实现原理 Mapper接口开发方法只需要程序员编写Mapper
2023-05-31

如何在Spring框架中实现动态代理

这篇文章给大家介绍如何在Spring框架中实现动态代理,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。动态代理,是一种通过运行时操作字节码,以达到增强类的功能的技术,也是Spring AOP操作的基础,关于AOP的内容,
2023-05-31

如何在 Linux 中使用动态和静态库

本篇内容介绍了“如何在 Linux 中使用动态和静态库”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!了解 Linux 如何使用库,包括静态库
2023-06-15

如何使用VB.NET动态代码

小编给大家分享一下如何使用VB.NET动态代码,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!使用VB.NET动态代码在运行时创建一个控件是在无法确定应用程序功能的
2023-06-17

怎么在Java中动态代理Cglib

这篇文章将为大家详细讲解有关怎么在Java中动态代理Cglib,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。常用的java框架有哪些1.SpringMVC,Spring Web MVC是一种
2023-06-14

Java 动态代理中Proxy的使用方法

本篇文章给大家分享的是有关Java 动态代理中Proxy的使用方法,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。动态代理可以提供对另一个对象的访问,同时隐藏实际对象的具体事实
2023-06-17

使用Java怎么实现静态代理和动态代理

本篇文章为大家展示了使用Java怎么实现静态代理和动态代理,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。代理模式代理模式(Proxy):为其他对象提供一个代理以控制对这个对象的访问。主要解决:在直接
2023-06-14

golang 如何使用反射实现动态代理模式

go中使用反射实现动态代理答案: 是的,可以通过反射在go中实现动态代理模式。步骤:创建自定义代理类型,包含目标对象引用和方法处理逻辑。为代理类型创建代理方法,在调用目标方法前或后执行额外逻辑。使用反射动态调用目标方法,使用reflect.
golang 如何使用反射实现动态代理模式
2024-05-01

Java动态代理如何实现

本篇内容介绍了“Java动态代理如何实现”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!JDK动态代理:利用反射机制生成一个实现代理接口的匿名
2023-06-30

怎么在java中实现动态代理

这篇文章给大家介绍怎么在java中实现动态代理,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。Java是什么Java是一门面向对象编程语言,可以编写桌面应用程序、Web应用程序、分布式系统和嵌入式系统应用程序。1、说明代
2023-06-14

java动态代理的简单使用

本篇内容主要讲解“java动态代理的简单使用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“java动态代理的简单使用”吧!//---------------接口package reflect_t
2023-06-02

怎么在java中实现CGLIB动态代理

怎么在java中实现CGLIB动态代理?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。Java的特点有哪些Java的特点有哪些1.Java语言作为静态面向对象编程语言的代表,
2023-06-14

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录