真实世界:使用WCF扩展在方法调用前初始化环境
OperationInvoker 介绍
OperationInvoker 是 WCF 运行时模型中在调用最终用户代码前的最后一个扩展点,OperationInvoker 负责最终调用 Service Operation,并且在 IOperationInvoker 中定义了操作调用的同步和异步模式。
在 WCF 的内部,实现了同步和异步的方法调用类:
- System.ServiceModel.Dispatcher.SyncMethodInvoker
- System.ServiceModel.Dispatcher.AsyncMethodInvoker
上述两个实现是方法调用的默认实现。
IOperationInvoker 接口定义
// Summary:
// Declares methods that take an object and an array of parameters extracted
// from a message, invoke a method on that object with those parameters, and
// return the method's return value and output parameters.
public interface IOperationInvoker
{
bool IsSynchronous { get; }
object[] AllocateInputs();
object Invoke(object instance, object[] inputs, out object[] outputs);
IAsyncResult InvokeBegin(object instance, object[] inputs, AsyncCallback callback, object state);
object InvokeEnd(object instance, out object[] outputs, IAsyncResult result);
}
问题描述
现在,我们需要在每个服务操作调用前为其单独准备 UnityContainer 环境,目的是保证每个服务操作调用所在的线程使用唯一个 UnityContainer。
假设,设计一个 UnityContainerScope 类来完成此工作。
public class UnityContainerScope : IDisposable
{
public static UnityContainerScope NewScope()
{
return new UnityContainerScope();
} public void Dispose()
{ }
}
则服务实现中需要为每个操作添加 using (var scope = UnityContainerScope.NewScope()) {} 来完成 Scope 初始化。
public class CalculatorService : ICalculatorService
{
public int Add(int a, int b)
{
using (var scope = UnityContainerScope.NewScope())
{
return a + b;
}
}
}
解决方案
通过实现 IOperationInvoker 接口,在指定的 Operation 调用前直接调用 UnityContainerScope (仅实现同步接口调用) 。
public class UnityContainerScopeOperationInvoker : IOperationInvoker
{
private IOperationInvoker originalInvoker; public UnityContainerScopeOperationInvoker(IOperationInvoker originalInvoker)
{
this.originalInvoker = originalInvoker;
} #region IOperationInvoker Members public object[] AllocateInputs()
{
return this.originalInvoker.AllocateInputs();
} public object Invoke(object instance, object[] inputs, out object[] outputs)
{
using (var scope = UnityContainerScope.NewScope())
{
return this.originalInvoker.Invoke(instance, inputs, out outputs);
}
} public IAsyncResult InvokeBegin(object instance, object[] inputs, AsyncCallback callback, object state)
{
return this.originalInvoker.InvokeBegin(instance, inputs, callback, state);
} public object InvokeEnd(object instance, out object[] outputs, IAsyncResult result)
{
return this.originalInvoker.InvokeEnd(instance, out outputs, result);
} public bool IsSynchronous
{
get { return this.originalInvoker.IsSynchronous; }
} #endregion
}
通过实现 UnityContainerScopeOperationBehaviorAttribute 来为需要初始化 Scope 的 Operation 进行定制。
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
public sealed class UnityContainerScopeOperationBehaviorAttribute : Attribute, IOperationBehavior
{
#region IOperationBehavior Members public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters)
{
} public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation)
{
} public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
{
if (dispatchOperation != null)
{
dispatchOperation.Invoker = new UnityContainerScopeOperationInvoker(dispatchOperation.Invoker);
}
} public void Validate(OperationDescription operationDescription)
{
} #endregion
}
使用方式:
[ServiceContract]
public interface ICalculatorService
{
[OperationContract]
[UnityContainerScopeOperationBehavior]
int Add(int a, int b);
}
扩展实现
当然,通常定义 Contracts 的程序集比较纯粹干净,不会有多于的类库引用。而如果 UnityContainerScopeOperationBehaviorAttribute 定义在其他类库中,比如通用类库,则 Contracts 程序集则必须引用该类库。
我们可以通过使用 IEndpointBehavior 来进行行为扩展,而无需在每个 OperationContract 定义上 HardCode 。
public class UnityContainerScopeEndpointBehavior : IEndpointBehavior
{
#region IEndpointBehavior Members public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
} public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
} public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
if (endpoint != null)
{
foreach (var operation in endpoint.Contract.Operations)
{
bool hasAdded = false; foreach (var item in operation.Behaviors)
{
if (item.GetType().FullName == typeof(UnityContainerScopeOperationBehaviorAttribute).FullName)
{
hasAdded = true;
break;
}
} if (!hasAdded)
{
operation.Behaviors.Add(new UnityContainerScopeOperationBehaviorAttribute());
}
}
}
} public void Validate(ServiceEndpoint endpoint)
{
} #endregion
}
参考资料
真实世界:使用WCF扩展在方法调用前初始化环境的更多相关文章
- 使用WCF扩展在方法调用前初始化环境
使用WCF扩展在方法调用前初始化环境 OperationInvoker 介绍 OperationInvoker 是 WCF 运行时模型中在调用最终用户代码前的最后一个扩展点,OperationInvo ...
- 真实世界:使用WCF扩展记录服务调用时间
WCF 可扩展性 WCF 提供了许多扩展点供开发人员自定义运行时行为. WCF 在 Channel Layer 之上还提供了一个高级运行时,主要是针对应用程序开发人员.在 WCF 文档中,它常被称为服 ...
- 使用WCF扩展记录服务调用时间
随笔- 64 文章- 0 评论- 549 真实世界:使用WCF扩展记录服务调用时间 WCF 可扩展性 WCF 提供了许多扩展点供开发人员自定义运行时行为. WCF 在 Channel Lay ...
- WCF扩展记录服务调用时间
WCF 提供了许多扩展点供开发人员自定义运行时行为. WCF 在 Channel Layer 之上还提供了一个高级运行时,主要是针对应用程序开发人员.在 WCF 文档中,它常被称为服务模型层(Serv ...
- 使用spring框架进行aop编程实现方法调用前日志输出
aop编程 之使用spring框架实现方法调用前日志输出 使用spring框架实现AOP编程首先需要搭建spring框架环境: 使用Spring框架实现AOP工程编程之后,不需要我们去写代理工厂了,工 ...
- WCF扩展
WCF 可扩展性 WCF 提供了许多扩展点供开发人员自定义运行时行为. WCF 在 Channel Layer 之上还提供了一个高级运行时,主要是针对应用程序开发人员.在 WCF 文档中,它常被称为服 ...
- Spring @Cacheable注解 && 事务@Transactional 在同一个类中的方法调用不生效
@Cacheable 注解在对象内部调用不会生效 代码示例:ProductServiceImpl.java public List<ProductInfoVO> getProductLis ...
- java方法调用及传参
静态方法:有static修饰的方法. 非静态方法:没有static修饰的方法. 方法调用: 一静态方法调用 静态方法/属性 1)一个类:直接调用. 2)不同类/不同文件: a: 类名.属性名/方法名 ...
- 实现jquery.ajax及原生的XMLHttpRequest跨域调用WCF服务的方法
关于ajax跨域调用WCF服务的方法很多,经过我反复的代码测试,认为如下方法是最为简便的,当然也不能说别人的方法是错误的,下面就来上代码,WCF服务定义还是延用上次的,如: namespace Wcf ...
随机推荐
- Oracle 查询库中所有表名、字段名、字段名说明,查询表的数据条数、表名、中文表名、
查询所有表名:select t.table_name from user_tables t;查询所有字段名:select t.column_name from user_col_comments t; ...
- nginx配置文件注释
#定义Nginx运行的用户和用户组user www www; #nginx进程数,建议设置为等于CPU总核心数.worker_processes 8; #全局错误日志定义类型,[ debug | in ...
- 117 FP页面无法查看
用户表示117 FP页面无法查看,提示如下错误: 跟进: 1.进入FP服务器可看到以下错误 这个错误的框就表示FP的一个进程报错,自动断掉了,需要重新跑一次EXIT,INIT,PLAN,EXPORT, ...
- html 高亮显示表格当前行
html在线模拟网:http://www.w3school.com.cn/tiy/t.asp?f=html_basic 高亮显示表格当前行 <html> <head> < ...
- Eclipse中Maven项目添加jar包
各个标签的含义如下: Overview:显示maven项目的一些基本信息Dependencies:添加jar包的页面Plugins:添加maven插件的页面.比如tomcat-maven-plugin ...
- grep 和 wc命令 --- !管道命令!
Linux系统中grep命令是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹 配的行打印出来.grep全称是Global Regular Expr ession Print,表示全局正则表 ...
- M1事后分析汇报总结
学霸网站项目Postmortem结果 设想和目标 1. 我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型场景有清晰的描述? 学霸网站为计算机学习提供了一个网上基地,在这里你 ...
- php匹配中文代码(字符串中包含中文或者全是中文)
<?php$str= "中文";//全部是汉字的$par = "\x80-\xff";$par2= chr(0xa1).'-'.chr(0xff);//包 ...
- Git常用命令(自己总是忘记,整理在这里)
1.git init 初始化一个空的git仓库 2.git clone +SSH地址 clone新的项目到本地 3.git add git add file 4.git commi ...
- FreeBSD_11-系统管理——{Part_2-核心}
一.Managing Services in FreeBSD Service restart will only work if it is set to YES in /etc/rc.conf. T ...