tags:

views:

74

answers:

3

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...
}
+1  A: 
  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
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
Reconsider your current job if your boss is too ignorant to let a developer or tester write (unit)tests :).
Webleeuw
uh no need to spend time testing something that the compiler can test.
stmax
@stmax: the compiler can't test it.
John Saunders
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
A: 

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
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
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
A: 

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