写在前面
在 Dynamics 365 项目中,插件往往是业务逻辑最集中、最容易踩坑的地方。
当项目周期拉长、人员更替或多人并行开发时,如果缺少清晰、统一的插件注释,维护成本会迅速放大。
下面整理的是我在多个 D365 项目中反复使用的一套 插件注释模板,目标只有一个:
让后来的人在不翻代码、不查注册记录的情况下,也能快速理解这个插件在 “什么时候、对什么、做了什么”。
插件注释模板示例
/// <summary>
/// <list type="bullet">
/// <item>模块:售前(示例)</item>
/// <item>功能</item>
/// <list type="number">
/// <item>功能描述 xxxx xxxx xxxx</item>
/// <item>功能描述 xxxx xxxx xxxx</item>
/// </list>
/// <item>Primary Entity: Lead</item>
/// <item>Message: Update</item>
/// <item>Update Attributes: qualifyingopportunityid, statecode</item>
/// <item>State: PostOperation</item>
/// <item>Mode: Synchronous</item>
/// </list>
/// </summary>
设计思路说明
- 模块 + 功能描述:从业务角度快速定位用途
- Primary Entity / Message / Stage / Mode:与插件注册信息一一对应
- Update Attributes:明确触发条件,避免“为什么会执行”的疑问
这套结构在代码审查、问题排查、插件迁移时都非常实用
Message/State/Mode 常见取值
| Message | 1 | Create |
| 2 | Update | |
| 3 | Delete | |
| 4 | Associate | |
| 5 | Disassociate | |
| 6 | SetStateDynamicEntity | |
| 7 | RetrieveMultiple | |
| 8 | Retrieve | |
| 9 | QualifyLead | |
| 10 | Assign | |
| State执行阶段 | 1 | Pre-validation |
| 2 | Pre-operation | |
| 3 | Post-operation | |
| Mode执行模式 | 1 | Synchronous |
| 2 | Asynchronous |
完整插件示例
using Microsoft.Xrm.Sdk;
using System;
namespace Blog.D365.Plugins.Account
{
/// <summary>
/// <list type="bullet">
/// <item>模块:售前(示例)</item>
/// <item>功能</item>
/// <list type="number">
/// <item>功能描述 xxxx xxxx xxxx</item>
/// <item>功能描述 xxxx xxxx xxxx</item>
/// </list>
/// <item>Primary Entity: Lead</item>
/// <item>Message: Update</item>
/// <item>Update Attributes: qualifyingopportunityid, statecode</item>
/// <item>State: PostOperation</item>
/// <item>Mode: Synchronous</item>
/// </list>
/// </summary>
public class AccountPostUpdate : IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
ITracingService tracer = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
try
{
if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
{
IOrganizationServiceFactory factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
IOrganizationService service = factory.CreateOrganizationService(context.UserId);
IOrganizationService serviceAdmin = factory.CreateOrganizationService(null);
Entity currentEntity = (Entity)context.InputParameters["Target"];
}
}
catch (Exception ex)
{
tracer.Trace($"AccountPostUpdate unexpected exception:\n{ex.Message}");
throw;
}
}
}
}
如果本文对你有所帮助,可以请我喝杯咖啡
(完)