Originally published at http://bit.ly/RIxgt9

How people do it today…

Often times when looking at Dynamics CRM plugin code that someone else has written – or that I have written in the past, I’m presented with a large collection of setup and validation code at the start of the Execute method. Overtime it becomes obvious that this is simply cluttering up our core Plugin code with what is really overhead infrastructure work.

public void Execute(IServiceProvider serviceProvider)

{

IPluginExecutionContext context = (Microsoft.Xrm.Sdk.IPluginExecutionContext)serviceProvider.GetService(typeof(Microsoft.Xrm.Sdk.IPluginExecutionContext));

IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));

IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);

ITracingService tracing = (ITracingService)serviceProvider.GetService(typeof(ITracingService));

//Okay, now lets do some actual work... 

tracing.Trace("Getting started...");

Entity target;

if (context.InputParameters["Target"] is Entity) target = (Entity)context.InputParameters["Target"];

}

Normally there would also be validation logic at this step to ensure that the values passed into the plugin are valid (i.e., in a Create or Update operation, verify the Contact entity and that a pre-image was provided.) For this posting I’m ignoring that so we can focus on just the basic plumbing above.

Is there a better way?

One of my favorite sayings is that “lazy people innovate.” So in that vein let me show you an easy way to do less work.

Looking at the above code you can see that we have four variable names we need to remember. In addition, we either need to type out this code or cut/paste for every plugin we create. At this point it is likely that different developers will start naming things differently, skipping steps, etc. For example, in the above code we could have skipped IOrganizationServiceFactory andIOrganizationService since the logic we implemented did not require them. Of course, if later on while developing this plugin we need to make a call to IOrganizationService then we’ll have to add this code and – with lazy developers being who we are – we are likely to just get added wherever we need it and not at the beginning of the method.

What I have been doing in my day-to-day work and strongly suggest to others is to abstract this plumbing code into a class thus reducing the above code the following:

public void Execute(IServiceProvider serviceProvider)
{

var p = new PluginSetup(serviceProvider);

//Okay, now lets do some actual work...

p.Tracing.Trace("Getting started...");

Entity target;

if (p.Context.InputParameters["Target"] is Entity) target = (Entity)p.Context.InputParameters["Target"];

}

As you can see we are taking the only input variable, IServiceProvider, and passing it to a constructor for PluginSetup thus returning an object which we have named p (which means the maximum additional keystrokes to access anything will be two.)

The PluginSetup class is shown below. It has a single public constructor which throws an exception if IServiceProvider is null. It then uses a fairly common pattern of instantiating a value for each property the first time it is accessessed. This pattern eliminates the problem, I mentioned earlier, where the developer has to know what they’ll need ahead of time. In this case there is no need to know if or when you’ll need to make a call to IOrganizationService.Create, the developer just calls p.Service.Execute and if the IOrganizationService has not been instantiated already it is taken care of effortlessly.

using System;
using System;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Client;

namespace Procentrix.Blog
{

    public class PluginSetup
    {

        private IPluginExecutionContext context;
        private IServiceProvider serviceProvider;
        private IOrganizationServiceFactory serviceFactory;
        private IOrganizationService service;
        private OrganizationServiceContext orgContext;
        private ITracingService tracing;
        public PluginSetup(IServiceProvider ServiceProvider)
        {

            if (ServiceProvider == null) throw new Exception("PluginSetup requires a valid IServiceProvider.");
            serviceProvider = ServiceProvider;

        }

        public IServiceProvider ServiceProvider
        {
            get { return serviceProvider; }
        }

        public IPluginExecutionContext Context
        {
            get
            {
                if (context != null)
                {
                    return context;
                }
                else
                {
                    context =
                        (Microsoft.Xrm.Sdk.IPluginExecutionContext)
                            ServiceProvider.GetService(typeof (Microsoft.Xrm.Sdk.IPluginExecutionContext));
                    return context;
                }
            }
        }

        public IOrganizationServiceFactory ServiceFactory
        {
            get
            {
                if (serviceFactory != null)
                {
                    return serviceFactory;
                }
                else
                {

                    serviceFactory =
                        (IOrganizationServiceFactory) ServiceProvider.GetService(typeof (IOrganizationServiceFactory));
                    return serviceFactory;
                }
            }
        }

        public IOrganizationService Service
        {
            get
            {
                if (service != null)
                {
                    return service;
                }
                else
                {
                    service = ServiceFactory.CreateOrganizationService(Context.UserId);
                    return service;
                }
            }
        }

        public OrganizationServiceContext ServiceContext
        {
            get
            {
                if (orgContext != null)
                {
                    return orgContext;
                }
                else
                {
                    orgContext = new OrganizationServiceContext(Service);
                    return orgContext;
                }
            }
        }

        public ITracingService Tracing
        {
            get
            {
                if (tracing != null)
                {
                    return tracing;
                }
                else
                {
                    tracing = (ITracingService) ServiceProvider.GetService(typeof (ITracingService));
                    return tracing;
                }
            }
        }
    }
}

Conclusion

Implementing the PluginSetup class (or something similar), can improve developer productivity by eliminating work and increasing standardization. In future posts I’ll show additional capabilities we can wrap into and around the PluginSetup class to further improve our efficiency and development experience.

Bonus Item

If you want, feel free to rename the properties in the class to give them shorter names (i.e., rename Context to ctx, etc.) This will just eliminate more keystrokes for developers. So long as you are standardized so that all plugins use the same class I see no problem is shortening the names.

Finally, a couple quick notes on this class. I know some people will balk at providing access toOrganizationServiceContext in a plugin. Feel free to delete it if you prefer. Also, theIOrganizationService will always use the IPluginExecutionContext.UserId, which would need to change if you are doing impersonation – you can implement that logic if needed and I’ll address it further in a future post.