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)开发(二)的更多相关文章

  1. MS CRM 2011的自定义和开发(11)——插件(plugin)开发(三)

    http://www.cnblogs.com/StoneGarden/archive/2012/02/06/2340661.html MS CRM 2011的自定义和开发(11)——插件(plugin ...

  2. MS CRM 2011的自定义和开发(11)——插件(plugin)开发(四)

    http://www.cnblogs.com/StoneGarden/archive/2012/02/08/2343294.html MS CRM 2011的自定义和开发(11)——插件(plugin ...

  3. MS CRM 2011的自定义和开发(11)——插件(plugin)开发(一)

    http://www.cnblogs.com/StoneGarden/archive/2012/02/02/2336147.html MS CRM 2011的自定义和开发(11)——插件(plugin ...

  4. 【Mybtais】Mybatis 插件 Plugin开发(一)动态代理步步解析

    需求: 对原有系统中的方法进行'拦截',在方法执行的前后添加新的处理逻辑. 分析: 不是办法的办法就是,对原有的每个方法进行修改,添加上新的逻辑:如果需要拦截的方法比较少,选择此方法到是会节省成本.但 ...

  5. Android组件化和插件化开发

    http://www.cnblogs.com/android-blogs/p/5703355.html 什么是组件化和插件化? 组件化开发就是将一个app分成多个模块,每个模块都是一个组件(Modul ...

  6. YYDS: Webpack Plugin开发

    目录 导读 一.cdn常规使用 二.开发一个webpack plugin 三.cdn优化插件实现 1.创建一个具名 JavaScript 函数(使用ES6的class实现) 2.在它的原型上定义 ap ...

  7. CRM 2011 开发中遇到的问题小结

    1.将Retrive 方法改成 RetrieveMultiple时 如果指定的ColumnSet 没有指定主键(entiryname+id),要显示增加实体的主键.否则在调用 Retrieve方法时返 ...

  8. Microsoft Dynamics CRM 2011的组织服务中的RetrieveMultiple方法(转)

    本篇文章,介绍Microsoft Dynamics CRM 2011的组织服务中的RetrieveMultiple方法. RetreiveMultiple方法,用于获取实体的多个实例,该方法的签名如下 ...

  9. Microsoft Dynamics CRM 2011 安装完全教程

    作者:卞功鑫,转载请保留.http://www.cnblogs.com/BinBinGo/p/4302612.html 环境介绍 WINDOWS 2008 R2 Datacenter Microsof ...

随机推荐

  1. LeetCode Sum Root to Leaf Numbers(DFS)

    题意: 给一棵二叉树,每个节点上有一个数字,范围是0-9,将从根到叶子的所有数字作为一个串,求所有串的和. 思路: 普通常规的DFS. /** * Definition for a binary tr ...

  2. ng-init

  3. 设计模式:Strategy 策略模式 -- 行为型

    设计模式 策略模式Strategy(对象行为型) 这是几年前写的文字(转载做的笔记更准确些),发觉还是废话多了点. 其实,核心就是5.结构中的UML图 5.1 和 5.2(新增).现在看这张图就觉得一 ...

  4. SQL编写

    //用户表,用户ID,用户名称create table t_user (user_id int,username varchar(20));//用户帐户表,用户ID,用户余额(单位分)create t ...

  5. Codeforces Round #126 (Div. 2)

    A. Cinema 假设当前要的位置为\((x, y)\),如果枚举答案的横坐标,那么每次找离\(y\)最近的纵坐标. 如果占用了位置\((x,y)\),需要要更新第\(x\)行的信息,而占用位置\( ...

  6. spark新能优化之reduceBykey和groupBykey的使用

    val counts = pairs.reduceByKey(_ + _) val counts = pairs.groupByKey().map(wordCounts => (wordCoun ...

  7. svn 安装 、使用(2)

    写在前面的话: p.s.有必要读一读,不然可能会浪费你的时间. 该篇是接着上一篇的,上一篇是看了很多人写的文章,汇总的一些可能的情况,最后还是没有成功.此篇是在一个同学的帮助下成功的,也是在自己做好的 ...

  8. ExtJS布局方式(layout)图文详解

    Auto默认布局 不给下级组件指定大小和位置 Absolute绝对布局 可使用坐标(x.y)进行布局 Accordion手风琴布局 实现Accordion效果的布局,也可叫可折叠布局.也就是说使用该布 ...

  9. [hdu 4416]Good Article Good sentence

    最近几天一直在做有关后缀自动机的题目 感觉似乎对后缀自动机越来越了解了呢!喵~ 这题还是让我受益颇多的,首先搞一个后缀自动机是妥妥的了 可是搞完之后呢? 我们来观察 step 这个变量,每个节点的 s ...

  10. 黑马程序员——JAVA基础之内部类,匿名内部类

    ------- android培训.java培训.期待与您交流! ---------- 内部类 将一个类定义在另一个类的里面,对里面那个类就称为内部类(内置类,嵌套类). 内部类访问特点: •  内部 ...