4

I'm building SQL expressions from LINQ Expressions and liking it verry much. However an issue with refactoring has come up. Suppose I want to check the Method of a MethodCallExpression, I would do something like this:

MethodCallExpression expr = ...  // An expression from somewhere...

if (expr.Method == typeof(SqlFilterExtensions).GetMethod("Like", BindingFlags.Static | BindingFlags.Public))
{
    // Generate the SQL...
}

It works great, but if someone was to rename, move or somehow alter the method, this would fail silently.

I have come up with one idea, but I find it ugly as H...

if (expr.Method == new Func<string,string,bool>(SqlFilterExtensions.Like).Method)
{
    // Generate the SQL...
}
John Saunders
  • 160,644
  • 26
  • 247
  • 397
LaZe
  • 692
  • 4
  • 14

3 Answers3

1
  1. It wouldn't fail silently if you had unit tests to test it.
  2. If you used ReSharper, it would offer to change the text in the string literal at the same time as renaming the method.
John Saunders
  • 160,644
  • 26
  • 247
  • 397
  • Sadly I don't have unittests on it, and my boss won't let me use time to add it. I use ReSharper, but not everyone does, and I can't trust people to know that string literals must be renamed. What I need is a compile error, so people know they have made an error. – LaZe Mar 04 '10 at 12:27
  • Reconsider your current job if your boss is too ignorant to let a developer or tester write (unit)tests :). – Webleeuw Mar 04 '10 at 12:31
  • uh no need to spend time testing something that the compiler can test. – stmax Mar 04 '10 at 12:37
  • 1
    @stmax: the compiler can't test it. – John Saunders Mar 04 '10 at 14:33
  • you're right the compiler cannot test the one with the string, but it can test the other one with the new Func<..>. i'd always prefer the one the compiler can test instead of writing code for a unit test. actually i think that "if (expr.Method == LikeMethod) {...}", where LikeMethod is a property that returns that new Func<..>(..).Method-thing, doesn't even look so ugly. and it's compile time checked. – stmax Mar 04 '10 at 19:44
1

I don't understand what you are doing, I think you could probably completely avoid some of the code you show here.

I wrote this "GetMemberName" extension method, you probably can do something with this code:

public static string GetMemberName<T, TResult>(
    this T anyObject, 
    Expression<Func<T, TResult>> expression)
{
    return ((MemberExpression)expression.Body).Member.Name;
}

// call as extension method, if you have a instance
string lengthPropertyName = "abc".GetMemberName(x => x.Length);

// or call as a static method, by providing the type in the argument
string lengthPropertyName = ReflectionUtility.GetMemberName(
    (string x) => x.Length);

Edit:

just to sketch up a solution:

public static bool IsMethod<TResult>(
  MethodInfo method, 
  Expression<Func<TResult>> expression)
{
  // I think this doesn't work like this, evaluate static method call
  return method == ((MemberExpression)expression.Body).Member;
}

if (IsMethod(expr.Method, () => SqlFilterExtensions.Like))
{
  // generate SQL
}
Stefan Steinegger
  • 63,782
  • 15
  • 129
  • 193
  • Thanks for the suggestion Stefan. However I think the "new Func<..." thing will be better, because that way I force a list of parameter-types on it. Still not liking it though... – LaZe Mar 04 '10 at 12:36
  • Just found out that calling the extension method like this doesn't work either, because you need arguments. You could either pass dummy arguments (eg. null) or pass the delegate the way you do it in your question. But you could enhance the syntax by letting the helper method creating the Func. – Stefan Steinegger Mar 04 '10 at 12:45
  • Mind you this approach has a corner case (see http://stackoverflow.com/questions/6658669/lambda-expression-not-returning-expected-memberinfo). Secondly, its better to check for unary expressions as in cases of boxed conversions like ` () => IntMethod()`. Also, not to nitpick, you need `((MethodCallExpression)expression.Body).Method` – nawfal Dec 13 '13 at 05:00
0

If you have control over the Like method, maybe you could work from there directly instead of inspecting the expressions later.

If you don't have control over the method there is no other way than to do it by comparing the name

Mel Gerats
  • 2,234
  • 1
  • 16
  • 33