Passing Property Names the "compiler-safe" Way

A common bad practice which I often find when browsing through code is to see people directly hard-code strings in their source code. I've also proposed some refactorings in some of my previous posts. Today I'd like to blog about a similar issue which targets the issue of object property referencing within code.

I guess most of us already had the case where you give a property of your entity like
SomeHelper.Validate(entityObject, "somePropertyName", value);
SomeHelper.Validate(entityObject, "someOtherPropertyName", value);
This "strange" assignment because SetProperty takes objects in a generic way and validates the specified property. Note, this is not real-world code, so don't be scared :) , but it may arise in similar ways throughout your code-base.
Another use case I was currently experiencing and which was the reason for writing this blog post is when announcing a problem about some property to the system user (i.e. in a log). In such a case you'd probably write
MyLogger.LogProblem("SomePropertyName", "Some message from a resource file");

So what's the problem with such code?
  • No compile-time-checking! Changing the property name of your object, won't give you any error during compile time but you may experience nice errors when the system is being used. Well ok, ReSharper does a nice job in also including such strings in refactorings, but still.
    These kind of bugs are heavy, since you may have difficulties in spotting them.
  • It is cumbersome to type and code because you have to remember the exact name of the property without any kind of Intellisense support.
These issues can be solved by using a nice Linq construct.
public static void LogProblem<T>(Expression<Func<T>> propertyExpression, string message)
{
string propertyName = GetPropertyName(propertyExpression);
if (propertyName == null)
throw new NullReferenceException("The name of the property couldn't be retrieved!");

LogEntry logEntry = new LogEntry()
{
Fieldname = propertyName,
MessageDescription = String.Format(message, propertyName)
};

logEntries.Add(logEntry);
}

public static string GetPropertyName<T>(Expression<Func<T>> expression)
{
MemberExpression body = (MemberExpression)expression.Body;
return body.Member.Name;
}
This can then be used very nicely by rewriting the logging instruction I mentioned before like this
MyLogger.LogProblem(() => myObjInstance.SomePropertyName, "Some message from a resource file");
Voilá, you have a compile-time, fully intellisense supported logging method now. The only thing I don't really like is the somehow strange-looking declaration of the property name by having to use () => ...
Kindle

Comments

0

Your ad here?