The Curse Of GlassCast

Background

.NET introduced the ability to create extension methods on existing classes. This feature allows us to easily add our own methods to exist classes without the need to create a sub-type.

With all the excitement of a kid with a new toy I created the GlassCast extension method to extend the standard Sitecore.Data.Items.Item class. The idea was that I wanted to create a really easy way to get a strongly typed representation of an item in situations where passing in an ISitecoreService might be difficult or where a one of conversion was needed, e.g. workflow, events, pipelines.

This is a decision I now regret and a great example of bad coding practice. In this blog post I will look at the problems it creates.

The Problem

The problem with GlassCast is that it hides some very important implementation details from the developer, let take a look at the method:

   public static T GlassCast<T>(this Item item, bool isLazy = false, bool inferType = false) where T : class
    {
        var service = new SitecoreService(item.Database);
        return item.GlassCast<T>(service, isLazy, inferType);
    }

Although simple in the middle the method we create an instance of the SitecoreService. This causes a problem because the SitecoreService has a lot of dependencies, if the application creates a single instance that is reused within a thread or request then this overhead is minimal. If however the application makes excessive use of GlassCast then we have a lot of instantiations which cause a lot of overhead. All this is hidden from the developer who simply writes the following an is none the wiser (not good):

var item = Sitecore.Context.Item;
var model = item.GlassCast<MyModel>();

From some basic performance tests we can see that for 10000 item requests that using one SitecoreService to get an item takes around 94ms vs 164ms when using GlassCast! That is a big difference.

The Solution

So how do we resolve the problem of GlassCast? Unfortunately we can't remove it from the Glass.Mapper.Sc code base without breaking a lots of solutions.

Therefore it means that those using Glass.Mapper should remove it from their solutions. Luckily this is very simple, if a block of code makes heavy use of GlassCast you can simply create an instance of SitecoreService and pass it in:

var sitecoreService = new SitecoreService("web");
var item = Sitecore.Context.Item;
var model1 = item.GlassCast<MyModel>(sitecoreService);
var model2 = item.GlassCast<MyModel2>(sitecoreService);

Personally I think it is better to remove GlassCast completely and use a method on the service itself:

var sitecoreService = new SitecoreService("web");
var item = Sitecore.Context.Item;
var model1 = sitecoreService.CreateType<MyModel>(item);
var model2 = sitecoreService.CreateType<MyModel2>(item);

SitecoreService also contains a cast method:

var sitecoreService = new SitecoreService("web");
var item = Sitecore.Context.Item;
var model1 = sitecoreService.Cast<MyModel>(item);
var model2 = sitecoreService.Cast<MyModel2>(item);

All solutions allow you to decided when the SitecoreService class is instantiated (i.e. in a controller, using IOC or other solution) and gives you more control over the lifetime of the service.

This code changes are not compulsory and are here as a best practice recommendation.

Summary

Where possible you should avoid using GlassCast and use the appropriate method on the SitecoreService for the following reasons:

  1. Slower
  2. Hides the instantiation of SitecoreService
  3. Lose the ability to control the lifecycle of the SitecoreService.
  4. Can easily be abused.

If you have any questions about this please contact me on Slack.

comments powered by Disqus