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 ...
随机推荐
- 归档 Archive、解档Unchive、 XML(一)
1 使用归档的方式保存文件 1.1 问题 归档是任何对象都可以实现的更常规的方式,可以进行归档的对象需要实现NSCoding协议,而且每个实例变量应该是基本数据类型或者是实现NSCoding协议的某个 ...
- opencv3.1包安装
由于之前零零碎碎安装了很多必要的库: 现在只需: (1)下载和解压包 https://github.com/daveselinger/opencv/tree/3.1.0-with-cuda8 这里的分 ...
- Think Python - Chapter 15 - Classes and objects
15.1 User-defined typesWe have used many of Python’s built-in types; now we are going to define a ne ...
- 使用dropbox 同步任意文件夹(MAC)
使用dropbox自动同步自己mac上的文件夹: -My_Programs /Users/foreverycc/Dropbox/My_Program # . must be full absolute ...
- iOS中的多线程及GCD
多线程中的一些概念 //任务:代码段 方法 线程就是执行这些任务 //NSThread类 创建线程 执行线程 [NSThread isMainThread]//判断是否是主线程 #import & ...
- ajax 上传
使用FormData,进行Ajax请求并上传文件:具体代码如下: html代码: <!DOCTYPE html><html lang="en"><he ...
- java正则表达式 非捕获组详解
这几天看了下正则表达式,对非捕获组(non-capturing)进行下总结.主要总结 1个 + 2组 一共5个.(?:X) (?=X) (?<=X) (?!X) (?<!X) 一.先从( ...
- 转ORA-28002: the password will expire within 7 days 解决方法
最后一步要改密码,否则还会报错. 1. 查看用户的profile设置: SELECT username,profile FROM dba_users; 一般用户的profile设置都为DEFAULT. ...
- php部分---面向对象:定义、实例化、构造函数、析构函数;
类 − 定义了一件事物的抽象特点.类的定义包含了数据的形式以及对数据的操作. 对象 − 是类的实例.一切皆对象.由类实例化出来的. 成员变量 − 定义在类内部的变量.该变量的值对外是不可见的,但是可以 ...
- html部分---样式属性;
<!--大小--> width:宽度 height:高度 <!--背景与前景--> "background-color:#0F0; 背景颜色 background-i ...