I have created the two following abstract classes that I use in my plugins and workflows:
/// <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();
}
}
And
/// <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();
}
}
Here's how I would create a plugin then:
public class CalculateTaxesOnUpdate : BasePlugin
{
public override void ExecutePluginLogic()
{
//From there I don't need to instanciate anything...neat!
}
}
This seems to work fine and helps to reduce boiler plate code when it comes to initiating instances of IOrganizationService
and ITracingService
namely.
But I've noticed that on some messages (ie: Update
of invoicedetail
) that are triggered with short delays, on the first execution, public properties of BasePlugin
are null
(which is expected) then on the following executions, they are already initiated (??). I noticed this being an issue because I had a Dispose
method in the base classes which would set properties to null after executing ExecutePluginLogic
and other threads would then try to use null
properties.
Since I'm not reusing them and re-initiating them anyways (which is what happens when you instanciate everything in Execute
anyways), I don't know if that's an issue, but am I going against best practices here ?