Using a Concurrent Dictionary Instead of Backing Properties

Hate them or love them, backing properties can be very handy for lazy loading values that you need in a multitude of of situations. For example you might have a base class for your controls or Sublayouts, Controllers and other renderings in a Sitecore context. That base class might be loaded with a ton of stuff, like search helpers, site settings and other things that every derived control might need. This is key because resolving those values could be an expensive operation and so your values are wrapped in a property with a getter that sets the result of the expensive method to a private backing property. This way you don’t execute the logic twice.
[csharp]private string data;
public string Data
{
get
{
if (data == null)
{
data = SomeOperation();
}
return data;
}
}[/csharp]
You end up with one private property that you need to declare for everyone public (or maybe protected/internal) property that you want to expose. That’s already a bit of duplication and file space. Next, if you use a tool like StyleCop with ReSharper you are told to always have XML comments for each one on the class members. So you run code cleanup, and now your private properties are all the way up at the top of the file, with their own XML comments. The code file is huge and will only get bigger, with each backing property taking up at least 5 lines, from the start of the XML comment of to the blank line underneath.
[csharp] #region Fields

/// <summary>
/// The data.
/// </summary>
private string data;

#endregion

#region Public Properties

/// <summary>
/// Gets the data.
/// </summary>
public string Data
{
get
{
if (this.data == null)
{
this.data = this.SomeOperation();
}

return this.data;
}
}

#endregion[/csharp]
Using .net 4.5 and up we can create a reusable class where a single instance will remove the need for multiple backing properties, and derived classes won’t need any backing properties at all. All we need to do is inherit from ConcurrentDictionary and create a few methods.
[csharp]public class BackingProperties : ConcurrentDictionary<string, object>[/csharp]
Now we need to have a way to to get and set values. The trick is that we want the property names to be the keys in the dictionary, and we don’t want to pass those keys in manually. Here’s where .NET 4.5’s CallerMemberName (explained here) comes in handy. We also want to be able to execute the logic to needed to set our value if we haven’t already.
[csharp]public T GetOrSetPropertyValue<T>(Func<T> method, [CallerMemberName] string propertyName = null)
{
if (this.ContainsKey(propertyName))
{
var value = this.GetPropertyValue<T>(propertyName);

return value;
}

var newValue = method();
this.SetPropertyValue(newValue, propertyName);

return newValue;
}[/csharp]
If this instance of BackingProperties contains the key, which in this case would be the property name of the property that called this method, then we get the property.
[csharp]public T GetPropertyValue<T>([CallerMemberName] string propertyName = null)
{
if (propertyName == null)
{
throw new ArgumentNullException("propertyName");
}

object value;
if (this.TryGetValue(propertyName, out value))
{
return (T)value;
}

return default(T);
}
[/csharp]
If it doesn’t have key then we execute the method and set its value.
[csharp]public T SetPropertyValue<T>(T newValue, [CallerMemberName] string propertyName = null)
{
if (propertyName == null)
{
throw new ArgumentNullException("propertyName");
}

if (!EqualityComparer<T>.Default.Equals(newValue, this.GetPropertyValue<T>(propertyName)))
{
this[propertyName] = newValue;
}

return newValue;
}[/csharp]
After all of that is in place we can use BackingProperties like this:
[csharp]#region Fields

/// <summary>
/// The backing properties.
/// </summary>
protected BackingProperties BackingProperties = new BackingProperties();

#endregion

#region Public Properties

/// <summary>
/// Gets the data.
/// </summary>
public string Data
{
get
{
return this.BackingProperties.GetOrSetPropertyValue(() => this.SomeOperation());
}
}

#endregion[/csharp]
You can pass any method or value that you want into GetOrSetPropertyValue. Your code is now cleaner because you only have a growing list of properties and not their backers. Any derived classes won’t have to declare their own BackingProperties. Its easier to write than an if statement because most of it will be filled in by IntelliSense and the logic value check happens elsewhere. There was no noticeable performance difference between using this functionality and regular private scoped backing properties.

You can find a solution containing the whole class with some extra functionality as well as a quick demo with examples here BackingProperties

Leave a Reply

Your email address will not be published. Required fields are marked *