Well OK, one string attached, a dependency on LINQ.Expressions.
You may be familiar with using Lambda expressions in HtmlHelper extensions as a way to get away from magic strings. For instance, for a display template, you could use Html.Display("Message")
which relies on the magic string "Message
", or instead you could use Html.DisplayFor(m => m.Message)
and the magic string disappears.
Or maybe you used ExpressionHelper.GetExpressionText
to replace magic string property names from a Model in a View. ExpressionHelper.GetExpressionText
has an overload that takes a Lambda expression and returns a string
representing the property name. For example, ExpressionHelper.GetExpressionText(p => p.Name)
would return the string
"Name
". I've found ExpressionHelper.GetExpressionText
useful when testing the UI layer and I need to find a control by its name to check its value.
Leverage Visual Studio
With this technique of using helpers utilizing Lambda expressions to replace magic strings, you can leverage Visual Studio’s IntelliSense and Debugger to ensure you get property names right, before runtime, before your bugs bite.
The ExpressionHelper
is part of Web.MVC but only gets property names from the Model and the HtmlHelper also only works in views. There are probably other parts of your application where you could use the same kind of functionality as these helpers and where you would like to leverage the Visual Studio IDE. It would be great to have a helper to be able to resolve any property name for any class to a string
safely, accurately, and anywhere in your application it is needed and to have Visual Studio help you use it.
There are other variations to a helper like this but I found this one in Scott Millett’s "Professional ASP.NET Design Patterns". He calls it PropertyNameHelper
and included it in his querying infrastructure namespace. The helper requires the LINQ.Expressions
library. Other classes in his querying namespace make use of LINQ so it made good sense for him to have it there. But I found it useful in other areas of my projects. One use is when I create business rules for validation routines. My business rule objects are lists that I populate with string
pairs of a property's name and its rule. I want to make sure to get the property name right, rather than making a typo, so I use the PropertyNameHelper
.
My version of PropertyNameHelper
is in a namespace called Helpers
where I keep other general purpose utilities and is a static
class with a static
method I’ve named StringNameFor
.
Using It Is Easy
Include a reference and a using
to the Helpers
namespace in your project and any classes your project references can be used by the helper. For a class named Product
with a property named Price
, you would use PropertyNameHelper.StringNameFor<Product>(p => p.Price)"
to return the string
"Price
". It's that easy.
IntelliSense makes sure that both Product
is a valid class and that Price
is a valid property. Using PropertyNameHelper
means you will always get "Price
". You won’t get "Pirce
" by mistake. And if you change the property name from Price
to Cost
, you can use refactoring tools to update all the references making your code a little less brittle and buggy. And using these helpers in your tests makes them less brittle too.
using System.Linq.Expressions;
namespace Helpers
{
public class PropertyNameHelper
{
public static string StringNameFor<T>(Expression<Func<T, object >> expression)
{
var expr = expression.Body as MemberExpression;
if (expr == null) {
var u = expression.Body as UnaryExpression;
expr = u.Operand as MemberExpression;
}
return expr.ToString().Substring(expr.ToString().IndexOf(".") + 1);
}
}
}