MS CRM 2011的自定义和开发(11)——插件(plugin)开发(二)
http://www.cnblogs.com/StoneGarden/archive/2012/02/06/2339490.html
MS CRM 2011的自定义和开发(11)——插件(plugin)开发(二)
上一篇文章《MS CRM 2011的自定义和开发(11)——插件(plugin)开发(一)》,介绍了Microsoft Dynamics CRM 2011中插件plugin的基本概念,事件处理子系统的概念,本篇文章将介绍插件的开发的方法。
可以使用与.Net Framework 4.0 CLR兼容的任何开发语言编写插件代码,笔者我只会C#,所以后续代码都是C#代码,如果是VB.Net或者精通其他语言的程序员同学,我就爱莫能助啦。
为了编写插件,需要在插件的Project中添加Microsoft.Xrm.SDK.dll以及Microsoft.Crm.Sdk.Proxy.dll两个程序集的引用。这两个程序集可以在SDK\bin目录下面找到。
插件都是Microsoft.Xrm.Sdk.IPlugin接口的实现类,所有的插件类都必须实现IPlugin接口。IPlugin接口只有一个Execute方法。该接口的代码如下所示:
public interface IPlugin
{
void Execute(IServiceProvider serviceProvider);
}
从上面代码可以看出Execute方法只有一个输入参数serviceProvider,该参数的类型是IServiceProvider,是事件执行管道传递给当前插件的所有消息的容器,存储了在插件中可能要使用到的各类对象。通过IServiceProvider接口的GetService方法,可以获取执行上下文IPluginExecutionContext、组织服务工厂IOrganizationServiceFactory以及跟踪服务ITracingService等实例。
一个插件的样例代码如下所示:

public class SamplePlugin: IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
// 获取插件执行上下文 IPluginExecutionContext context =
(IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext)); // 获取组织服务工厂实例 IOrganizationServiceFactory factory =
(IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
//获取组织服务实例
IOrganizationService service = factory.CreateOrganizationService(context.UserId); //获取跟踪服务
ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService)); try
{
// 插件业务逻辑代码
}
catch (FaultException<OrganizationServiceFault> ex)
{
//异常处理代码
}
}
}

插件执行上下文IPluginExecutionContext中,包括有事件处理管道传递给插件的各类信息,包括执行插件的运行时环境、执行管道相关信息以及触发Web服务的实体实例信息。IPluginExecutionContext接口中的成员列表如下所示:
|
名称 |
说明 |
|
ParentContext |
从父管道操作中获取执行上下文信息。父子管道产生原因在于CRM系统中某些消息请求可能会产生其他消息请求。举例来说AssignRequest请求会产生一个UpdateRequest请求,如果两个插件A和U分别订阅了AssignRequest消息和UpdateRequest消息,那么在AssignRequest产生时,插件A、插件U将依次执行,此时插件U的执行上下文的ParentContext属性将被赋予插件A的执行上下文。 |
|
Stage |
获取同步执行模式插件在执行管道中所处的阶段 |
IPluginExecutionContext接口继承自IExecutionContext接口,在IExecutionContext接口中,包含了大量的有关上下文的信息,如下表所示:
|
名称 |
说明 |
|
BusinessUnitId |
获取执行管道所处理的实体实例的业务部门GUID。 |
|
CorrelationId |
该属性的用途CRM平台为了避免出现无限死循环 |
|
Depth |
获取当前插件在调用堆栈中的深度。也是为了避免出现无限死循环。插件开发人员可以在插件代码中对该属性进行判断从而避免出现无限死循环。经常的一种使用情景是,订阅了UpateRequest的插件代码中还执行了Update操作。 |
|
InitiatingUserId |
获取当前执行事件管道的系统用户的GUID. |
|
InputParameters |
获取触发插件执行的请求消息参数. |
|
IsExecutingOffline |
获取当前插件是否运行在脱机环境中 |
|
IsInTransaction |
获取插件是否执行在数据库事务中。 |
|
IsOfflinePlayback |
如果插件可以运行在脱机环境中,那么在客户端与CRM服务器同步时,很可能由于数据同步造成服务器端同一插件再次执行一遍,从而导致数据出现了错误,此时,就需要在插件中使用本数据判断,是否是由于离线客户端与CRM服务器同步触发了本插件的运行。 |
|
IsolationMode |
判断插件是否执行在沙盒Sandbox中。 |
|
MessageName |
获取当前事件管道所处理的请求消息 |
|
Mode |
获取插件执行模式:同步执行还是异步执行. |
|
OperationCreatedOn |
在与Azure云进行集成的时候用到的。 |
|
OperationId |
|
|
OrganizationId |
获取实体实例所属组织的GUID. |
|
OrganizationName |
获取实体实例所属组织的唯一名称. |
|
OutputParameters |
获取平台核心操作完成后的响应消息参数. |
|
OwningExtension |
获取相关联的SdkMessageProcessingingStep对象. |
|
PostEntityImages |
主要用于UpdateRequest消息中,分别获取核心操作之前以及之后实体的快照、映像信息 |
|
PreEntityImages |
|
|
PrimaryEntityId |
事件管道正在处理的实体实例的GUID |
|
PrimaryEntityName |
事件管道正在处理的实体的逻辑名称. |
|
RequestId |
事件管道正在处理的请求的GUID. |
|
SharedVariables |
获取/设置插件之间传递的自定义属性值. |
当触发了插件订阅的事件时,CRM会创建、填充执行上下文,并将其作为Execute方法的输入参数,传递给Execute方法,从而,插件执行代码就可以使用这些上下文信息了。
在上下文中,有几个非常重要的属性,是插件代码中经常会使用到的:
输入参数InputParameters以及输出参数OutputParameters,这两个属性的基本信息已经在上面的列表中列出了,在此不赘述。下面主要看一下这两个属性的类型:ParameterCollection,ParameterCollection究其根本而言,是IEnumerable<KeyValuePair<TKey, TValue>>类型,即可遍历的键值对集合。由此,在插件代码中通过给定键值,就可以访问对应的数据值了,而键值就是各类请求消息中的公共属性的名称。例如CreateRequest中,有一个属性名为Target,包含了待创建的实体实例信息,是Entity类型,那么若要在CreateRequest触发的插件中访问带创建的实体实例信息,就可以使用如下代码获取:
Entity entity = (Entity)context.InputParameters[“Target”];
对于OutputParameters属性,也是类似的,只不过键值名称信息来自于相关的响应信息属性,而不再是请求消息中的属性名称了,其访问的方式和InputParameters属性的访问类似,不再赘述。
前期映像PreEntityImages和后期映像PostEntityImages,存储了平台核心操作之前与之后的快照。可以在插件注册的过程中,指定快照中需要存储的属性。需要注意的是,某些事件是缺少前期或者后期映像的。例如对于创建,是没有前期映像的,对于Delete是没有后期映像的。映像的类型是EntityCollection,本质和ParameterCollection类型是类似的,可以通过给定键值访问对应的映像数据,而键值的名称是在注册插件,设定映像的名称时候设定的。
除了执行上下文以外,绝对大多数情况下,还需要访问MS CRM系统的组织服务,那么可以通过从serviceProvider对象中获取组织服务工厂,而后由组织服务工厂的CreateOrganizationService方法创建组织服务的实例。代码可以参看上面的样例代码。在此不赘述。
下面列出了一个简单的插件,执行于客户Account的Pre Create事件上。处理的业务逻辑是,如果End User没有为客户编码字段赋值,那么插件就为该字段赋一个随机值。

using System; // Microsoft Dynamics CRM的命名空间之一
using Microsoft.Xrm.Sdk; namespace Microsoft.Crm.Sdk.Samples
{
public class AccountNumberPlugin: IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
// 获取执行上下文
IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext)); // InputParameters属性包含所有输入参数数据
if (context.InputParameters.Contains("Target") &&
context.InputParameters["Target"] is Entity)
{
// 从输入参数中获取Target参数
Entity entity = (Entity)context.InputParameters["Target"];
//检测输入的Target参数,判断其逻辑名称是否是account.
if (entity.LogicalName == "account")
{
// 判断客户记录的客户编码字段accountnumber是否有值
if (entity.Attributes.Contains("accountnumber") == false)
{
// 没有客户编码,那么赋一个随机数字
Random rndgen = new Random();
entity.Attributes.Add("accountnumber", rndgen.Next().ToString());
}
else
{
// 抛出一个错误,注意,错误的类型!
throw new InvalidPluginExecutionException("The account number can only be set by the system.");
}
}
}
}
}
}

上面就是一个简单的插件类的代码,仅仅是一个样例,具体的插件代码编写,还是要根据实际的业务情况确定的。
MS CRM 2011的自定义和开发(11)——插件(plugin)开发(二)的更多相关文章
- MS CRM 2011的自定义和开发(11)——插件(plugin)开发(三)
http://www.cnblogs.com/StoneGarden/archive/2012/02/06/2340661.html MS CRM 2011的自定义和开发(11)——插件(plugin ...
- MS CRM 2011的自定义和开发(11)——插件(plugin)开发(四)
http://www.cnblogs.com/StoneGarden/archive/2012/02/08/2343294.html MS CRM 2011的自定义和开发(11)——插件(plugin ...
- MS CRM 2011的自定义和开发(11)——插件(plugin)开发(一)
http://www.cnblogs.com/StoneGarden/archive/2012/02/02/2336147.html MS CRM 2011的自定义和开发(11)——插件(plugin ...
- 【Mybtais】Mybatis 插件 Plugin开发(一)动态代理步步解析
需求: 对原有系统中的方法进行'拦截',在方法执行的前后添加新的处理逻辑. 分析: 不是办法的办法就是,对原有的每个方法进行修改,添加上新的逻辑:如果需要拦截的方法比较少,选择此方法到是会节省成本.但 ...
- Android组件化和插件化开发
http://www.cnblogs.com/android-blogs/p/5703355.html 什么是组件化和插件化? 组件化开发就是将一个app分成多个模块,每个模块都是一个组件(Modul ...
- YYDS: Webpack Plugin开发
目录 导读 一.cdn常规使用 二.开发一个webpack plugin 三.cdn优化插件实现 1.创建一个具名 JavaScript 函数(使用ES6的class实现) 2.在它的原型上定义 ap ...
- CRM 2011 开发中遇到的问题小结
1.将Retrive 方法改成 RetrieveMultiple时 如果指定的ColumnSet 没有指定主键(entiryname+id),要显示增加实体的主键.否则在调用 Retrieve方法时返 ...
- Microsoft Dynamics CRM 2011的组织服务中的RetrieveMultiple方法(转)
本篇文章,介绍Microsoft Dynamics CRM 2011的组织服务中的RetrieveMultiple方法. RetreiveMultiple方法,用于获取实体的多个实例,该方法的签名如下 ...
- Microsoft Dynamics CRM 2011 安装完全教程
作者:卞功鑫,转载请保留.http://www.cnblogs.com/BinBinGo/p/4302612.html 环境介绍 WINDOWS 2008 R2 Datacenter Microsof ...
随机推荐
- LeetCode Combination Sum III (DFS)
题意: 在1-9这9个数字中选择k个出来,若他们的和为n,则加入答案序列,注意升序. 思路: 用DFS的方式,每次决定一个数字,共决策k次.假设上个决策是第i位为5,那么i+1位的范围就是6-9. c ...
- centos 输入密码正确进不去系统
国庆长假之后,上班,第一件事就是连接开发服务器进行开发,结果发现死活进不去系统.一开始以为是用户名和密码错误,后来发现怎么输入都是进不去系统,密码输入是肯定正确的. google了一下,发现有人说是密 ...
- SecureCRT相关
-------------------------------------------------- 如何解决SecureCRT汉字乱码的问题? 选择工具栏上的“选项”菜单在打开的下拉菜单中选择“会话 ...
- word 无法显示图片问题解决
1 打开Word文档,点击“Office按钮”→“Word选项”. 2 在打开的“Word选项”对话框中,点击左侧的“高级”选项卡,在右侧找到“显示文档内容”栏目,取消勾选“显示图片框”.
- PostgreSQL增删数据命令示例
在PostgreSQL中如何用简单的几条SQL语句生成大量的测试数据呢? 此处,我简单的写一个例子,供参考(在Postgresql9.1下面做的): (1)生成一万条测试数据的表foo mydb=# ...
- Core Java Volume I — 4.4. Static Fields and Methods
4.4. Static Fields and MethodsIn all sample programs that you have seen, the main method is tagged w ...
- code::blocks的快捷键汇总
编辑部分: Ctrl + A:全选 Ctrl + C:复制 Ctrl + X: 剪切 Ctrl + V:粘贴 Ctrl + Z:撤销 Ctrl + S:保存 Ctrl + Y / Ctrl + S ...
- 基于时间延迟的Python验证脚本
自己写的一段Python脚本,经常拿来验证一些sqlmap等工具跑不出数据的网站. GET类型: import urllib import urllib2 import time payloads = ...
- RViz 实时观测机器人建立导航2D封闭空间地图过程 (SLAM) ----27
原创博客:转载请表明出处:http://www.cnblogs.com/zxouxuewei/ ROS提供了非常强大的图形化模拟环境 RViz,这个 RViz 能做的事情非常多.今天我们学习一下如何使 ...
- Eclipse反编译插件jad安装
下载jadClipse地址: 链接: http://pan.baidu.com/s/1kTN4TPd 提取码: 3fvd 将net.sf.jadclipse_3.3.0.jar拷贝到eclipse的 ...