TL; DR;
Reflection is fine if you are not using Emit or Compile . In the question, the value is retrieved for FieldInfo , but it is not retrieved for PropertyInfo . Make sure you can get BOTH.
if ((expression.Member as PropertyInfo) != null) { // get the value from the PROPERTY } else if ((expression.Member as FieldInfo) != null) { // get the value from the FIELD } else { throw new InvalidMemberException(); }
Long term version
So the comments pointed me in the right direction. I worked a bit with getting PropertyInfo, but in the end, here's what I came up with.
private void VisitMemberAccess(MemberExpression expression, MemberExpression left) { // To preserve Case between key/value pairs, we always want to use the LEFT side of the expression. // therefore, if left is null, then expression is actually left. // Doing this ensures that our `key` matches between parameter names and database fields var key = left != null ? left.Member.Name : expression.Member.Name; // If the NodeType is a `Parameter`, we want to add the key as a DB Field name to our string collection // Otherwise, we want to add the key as a DB Parameter to our string collection if (expression.Expression.NodeType.ToString() == "Parameter") { _strings.Add(string.Format("[{0}]", key)); } else { _strings.Add(string.Format("@{0}", key)); // If the key is being added as a DB Parameter, then we have to also add the Parameter key/value pair to the collection // Because we're working off of Model Objects that should only contain Properties or Fields, // there should only be two options. PropertyInfo or FieldInfo... let extract the VALUE accordingly var value = new object(); if ((expression.Member as PropertyInfo) != null) { var exp = (MemberExpression) expression.Expression; var constant = (ConstantExpression) exp.Expression; var fieldInfoValue = ((FieldInfo) exp.Member).GetValue(constant.Value); value = ((PropertyInfo) expression.Member).GetValue(fieldInfoValue, null); } else if ((expression.Member as FieldInfo) != null) { var fieldInfo = expression.Member as FieldInfo; var constantExpression = expression.Expression as ConstantExpression; if (fieldInfo != null & constantExpression != null) { value = fieldInfo.GetValue(constantExpression.Value); } } else { throw new InvalidMemberException(); } // Add the Parameter Key/Value pair. Parameters.Add("@" + key, value); } }
Essentially, if Member.NodeType is a Parameter , I will use it as an SQL field. [FieldName]
Otherwise, I use it as an SQL parameter @FieldName ... back, I know.
If Member.NodeType NOT a parameter, then I check to see if it is either a Model Field or a Model Property . From there I get the appropriate value and add a key / value pair to the dictionary, which will be used as SQL parameters.
As a result, I create a line that looks something like
SELECT * FROM TableName WHERE [FieldName] = @FieldName
Then the parameters are passed
var parameters = new Dictionary<string, object> Parameters; parameters.Add("@FieldName", "The value of the field");