写在前面

在 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
2Update
3Delete
4Associate
5Disassociate
6SetStateDynamicEntity
7RetrieveMultiple
8Retrieve
9QualifyLead
10Assign
State
执行阶段
1 Pre-validation
2Pre-operation
3Post-operation
Mode
执行模式
1 Synchronous
2Asynchronous

完整插件示例

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;
            }
        }
    }
}

如果本文对你有所帮助,可以请我喝杯咖啡

(完)