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 ...
随机推荐
- Hashing filters for very fast massive filtering
If you have a need for thousands of rules, for example if you have a lot of clients or computers, al ...
- C. Polycarpus' Dice
在每个位置讨论一下最大值最小值的取值范围就行 #include<cstdio> #include<iostream> #define maxn 200003 using nam ...
- lable自动适配大小
#import "ViewController.h" @interface ViewController () @end @implementation ViewControlle ...
- 顺序表及其多种实现方式 --- C/C++
所谓顺序表,即线性表的顺序存储结构.下面给出的是数据结构---线性表的定义. ADT List{ 数据对象: 线性表的数据对象的集合为{a1,a2,a3,...,an},每个元素的类型为ElemTyp ...
- timus 1136 Parliament(二叉树)
Parliament Time limit: 1.0 secondMemory limit: 64 MB A new parliament is elected in the state of MMM ...
- swift与OC混编高级教程之混编框架的创建和调用
首先创建一个project取个名字叫“MyMixed”,选择iOS-framework&library-cocoa touch framework 然后在里面创建一个SwiftView.swi ...
- IOS开发之SWIFT
Swift是苹果2014年推出的全新的编程语言,它继承了C语言.ObjC的特性,且克服了C语言的兼容性问题.Swift发展过程中不仅保留了 ObjC很多语法特性,它也借鉴了多种现代化语言的特点,在其中 ...
- kuangbin_ShortPath L (POJ 2502)
dij部分还是跟模板差不多的 但是这题的难点是处理输入 或者说理解题意 事实上每个点之间都是可以走的......WA了好几发就因为没意识到同一条路线上的各个站点之间居然也可以走得比车子快.... PS ...
- kuangbin_ShortPath K (POJ 3159)
很简单的模板题 放在K那么后的位置的原因大概是 光看题意并不是很容易想到是用最短路解吧 奈何kuangbin分在了最短路专题 一发水过 #include <iostream> #inclu ...
- Linux驱动设计—— 内核模块(一)
Linux内核理论基础 组成Linux内核的5个子系统:进程调度(SCHED)/内存管理(MM)/虚拟文件系统(VFS)/网络接口(NET)/进程间通信(IPC). 进程调度(SCHED) 在设备驱动 ...