真实世界:使用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 ...
随机推荐
- 【译】为什么这样宏定义#define INT_MIN (-2147483647 - 1)?
2的32次方为2147483648*2,0~(2147483648*2-1)这是32位机上无符号整数代表的范围.而32机的int范围为-2147483648~+2147483647 stackover ...
- mybaits中xml文件大于号和小于号的处理方法
1.转义字符 原符号 < <= > >= & ' " 替换符号 < <= > >= & ' " 2 ...
- Log4j 配置 的webAppRootKey参数问题
为了让Web项目中的Spring 使用Log4j做如下配置: 1.在web.xml中添加如下内容: <!--如果不定义webAppRootKey参数,那么webAppRootKey就是缺省的&q ...
- 使用网易ubuntu镜像加速软件包安装
用vi工具编辑文件 sudo vi /etc/apt/sources.list 以trusty(14.04)为例,插入下面内容到文件的最前面: deb http://mirrors.163.com/u ...
- scala 学习:object 和class, trait
object: Scala中没有静态修饰符,static,在object下的成员全部都是静态的,如果在类中声明了与该类相同的名字的object则该object是该类的"半生对象", ...
- iOS开发-Alcatraz插件管理
CocoaPod负责iOS开发中的引用类库的管理,Alcatraz中文翻译阿尔卡特拉斯岛,也有人称之为恶魔岛,主要是负责管理第三方Xcode 插件.模版以及颜色配置的工具,直接集成到 Xcode 的图 ...
- LeetCode OJ 147. Insertion Sort List
Sort a linked list using insertion sort. Subscribe to see which companies asked this question 解答 对于链 ...
- MATLAB - 练习程序,直方图均衡化
直方图均衡化的作用是图像增强. 有两个问题比较难懂,一是为什么要选用累积分布函数,二是为什么使用累积分布函数处理后像素值会均匀分布. 第一个问题.均衡化过程中,必须要保证两个条件:①像素无论怎么映射, ...
- JSON基本用法
JSON基本用法 2016-08-10 16:42:19 JSON的全称是“JavaScript Object Notation”,意思是JavaScript对象表示法,它是一种基于文本,独立于语 ...
- hihoCoder 1305 区间求差
#1305 : 区间求差 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 给定两个区间集合 A 和 B,其中集合 A 包含 N 个区间[ A1, A2 ], [ A3, ...