我已经创建了我在插件和工作流中使用的两个抽象类:
/// <summary>
/// Base plugin class. Provides access to most often used Xrm resources.
/// </summary>
public abstract class BasePlugin : IPlugin
{
public IServiceProvider ServiceProvider { get; set; }
public ITracingService TracingService { get; set; }
public IPluginExecutionContext PluginContext { get; set; }
public IOrganizationService Service { get; set; }
public void Execute(IServiceProvider serviceProvider)
{
ServiceProvider = serviceProvider;
TracingService =
(ITracingService)serviceProvider.GetService(typeof(ITracingService));
PluginContext = (IPluginExecutionContext)
serviceProvider.GetService(typeof(IPluginExecutionContext));
IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
Service = serviceFactory.CreateOrganizationService(PluginContext.UserId);
ExecutePluginLogic();
}
public virtual void ExecutePluginLogic()
{
throw new NotImplementedException();
}
}和
/// <summary>
/// Base workflow class. Provides access to most often used Xrm resources.
/// </summary>
public abstract class BaseWorkflow : CodeActivity
{
public CodeActivityContext CodeActivityContext { get; set; }
public IWorkflowContext WorkflowContext { get; set; }
public ITracingService TracingService { get; set; }
public IOrganizationService Service { get; set; }
protected override void Execute(CodeActivityContext context)
{
IOrganizationServiceFactory serviceFactory = context.GetExtension<IOrganizationServiceFactory>();
CodeActivityContext = context;
TracingService = context.GetExtension<ITracingService>();
WorkflowContext = context.GetExtension<IWorkflowContext>();
Service = serviceFactory.CreateOrganizationService(WorkflowContext.UserId);
ExecuteWorkflowLogic();
}
public virtual void ExecuteWorkflowLogic()
{
throw new NotImplementedException();
}
}下面是我如何创建一个插件:
public class CalculateTaxesOnUpdate : BasePlugin
{
public override void ExecutePluginLogic()
{
//From there I don't need to instanciate anything...neat!
}
}当涉及到启动IOrganizationService和ITracingService的实例时,这似乎很好,并且有助于减少锅炉板代码。
但是我注意到,在一些消息(即:Update of invoicedetail)上,在第一次执行时,BasePlugin的公共属性是null (这是预期的),然后在接下来的执行中,它们已经启动(??)。我注意到这是一个问题,因为基类中有一个Dispose方法,它将在执行ExecutePluginLogic之后将属性设置为null,然后其他线程将尝试使用null属性。
由于我不会重用它们并以任何方式重新启动它们(这是在Execute中实例化所有东西时会发生的情况),所以我不知道这是否是一个问题,但我是否违背了这里的最佳实践?
发布于 2016-06-13 17:37:41
仅仅因为它是一个基类并不能消除CRM插件(和工作流)中类级变量的问题。
为了提高性能,Microsoft Dynamics缓存插件实例。插件的执行方法应该是无状态的,因为并不是每次插件调用都会调用构造函数。此外,多个系统线程可以同时执行插件.每个调用状态信息都存储在上下文中,因此不应使用全局变量或尝试将任何数据存储在成员变量中,以便在下一次插件调用期间使用,除非该数据是从提供给构造函数的配置参数中获取的。对插件注册的更改将导致重新初始化插件。
类级变量违反了这种无状态需求。
我的建议是重写插件(然后对工作流执行同样的操作),使对象能够保存对Execute的每次调用的引用,从而允许代码满足无状态需求。
public class CrmObjects
{
public IServiceProvider ServiceProvider { get; set; }
public ITracingService TracingService { get; set; }
public IPluginExecutionContext PluginContext { get; set; }
public IOrganizationService Service { get; set; }
}
public abstract class BasePlugin : IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
var crmObjects = new CrmObjects();
crmObjects.ServiceProvider = serviceProvider;
crmObjects.TracingService =
(ITracingService)serviceProvider.GetService(typeof(ITracingService));
crmObjects.PluginContext = (IPluginExecutionContext)
serviceProvider.GetService(typeof(IPluginExecutionContext));
IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
crmObjects.Service = serviceFactory.CreateOrganizationService(crmObjects.PluginContext.UserId);
ExecutePluginLogic(crmObjects);
}
public virtual void ExecutePluginLogic(CrmObjects crmObjects)
{
throw new NotImplementedException();
}
}几年前,我写了一篇关于做类似事情的博客文章,http://nicknow.net/dynamics-crm-2011-abstracting-plugin-setup/。在模型中,我描述了它不依赖于基类,而是使用在Execute方法的第一行上实例化的类来完成相同的概念。从那以后,我转到了一个基类模型--类似于这个设计。当我有机会的时候,我会把它放到GitHub上。
发布于 2018-03-01 15:12:34
此外,即使您曾经使基类泛化(可能基于它检索的上下文类型),您仍然需要将: IPlugin接口添加到所有插件中,即使基类定义了它。
https://stackoverflow.com/questions/37792030
复制相似问题