I am developing data-interfacing that converts between two different data models. However, I must be sure that all required fields exist. Therefore I have written this utility class that I can easily use to verify required fields.
However I am unsure whether this is the best way because of the expression that needs to be compiled and the usage of reflection. Any feedback is welcome!
Usage
public OutputDataElement DetermineRetailTransactionShopperType(IHeaderEntity headerEntity)
{
Ensure.IsNotNull(() => headerEntity);
Ensure.IsNotNull(() => headerEntity.ShopId, "headerEntity");
// Some mapping logic removed from the example
}
Utility
/// <summary>
/// Helper class able to ensure expectations
/// </summary>
public static class Ensure
{
public static void IsNotNull<T>(Expression<Func<T>> property) where T : class
{
IsNotNullImpl(property, null);
}
public static void IsNotNull<T>(Expression<Func<T>> property, string paramName) where T : class
{
IsNotNullImpl(property, paramName);
}
private static void IsNotNullImpl<T>(Expression<Func<T>> property, string paramName) where T : class
{
// Compile the linq expression
Func<T> compiledFunc = property.Compile();
// Invoke the linq expression to get the value
T fieldValue = compiledFunc.Invoke();
// Check whether we have a value
if ((fieldValue is string && fieldValue.ToString() == string.Empty) || (fieldValue == null))
{
// We have no value. Get the initial expression
var expression = (MemberExpression)property.Body;
// log information about the expression that failed
throw new ArgumentException(string.Format("Missing required field '{0}'", expression.Member.Name), string.IsNullOrEmpty(paramName) ? null : paramName);
}
}
}
1 Answer 1
I don't see any unnecessary reflection in your code.
One think that could be simplified is your check for string.Empty
:
if (fieldValue == null || fieldValue as string == string.Empty)
-
\$\begingroup\$ Hmm, Just because
fieldValue != null
, doesn't mean you can cast it as a string without throwing an exception. \$\endgroup\$Alain– Alain2012年07月05日 23:58:50 +00:00Commented Jul 5, 2012 at 23:58 -
\$\begingroup\$ I just simplified the code that was in the question. I don't understand why would it have to throw an exception. \$\endgroup\$svick– svick2012年07月06日 00:47:15 +00:00Commented Jul 6, 2012 at 0:47
-
\$\begingroup\$ He checked fieldValue is string before casting it to a string. If you cast something that's not a string to a string it's not the same as calling Object.ToString() - it will cause an exception. \$\endgroup\$Alain– Alain2012年07月06日 03:56:39 +00:00Commented Jul 6, 2012 at 3:56
-
\$\begingroup\$ That's exactly why I'm using
as
. It will never throw an exception. If the object is a different type, it will returnnull
. \$\endgroup\$svick– svick2012年07月06日 07:24:44 +00:00Commented Jul 6, 2012 at 7:24