0

Lets say I have a method with the following signature:

public void MyMethod(Func<int> expression)
{
    // Does work
}

And I call this method as follows:

int intProperty = 7;
MyMethod(() => intProperty);

Is their some way that I could call this method without using the lambda? So I want it to look like this:

MyMethod(intProperty);

It does not matter to me if the method signature has to change - I am kind of counting on that. The reason I am trying to do this is because you can inspect additional information about the initial property when its passed in as a function that I need to be able to access.

I don't believe that using Reflection inside of MyMethod would work here, as I want information about the original parameter. Their are ways of getting information such as its name from a function, which is what I want to be able to retrieve. I am already able to do this. So, in the example above, MyMethod would be able to tell that the name of the property that was passed in was named intProperty.

NOTE: This is a simplified example. I am well aware I could just pass in the property if that's all I wanted. BUT I want additional information about the original property that the Func is capturing here, such as its original name.

lehn0058
  • 19,977
  • 15
  • 69
  • 109
  • 3
    I'm sorry but there isn't a built in way to do that. – Daniel A. White Mar 08 '13 at 13:52
  • 1
    The last example is equivalent to `MyMethod(int)` so you can do just that. – Zdeslav Vojkovic Mar 08 '13 at 13:56
  • What do you mean by "you can inspect additional information about the initial property when its passed in as a function?" Perhaps your example requires some clarification. – Kenneth K. Mar 08 '13 at 14:25
  • I have to ask. Why do you want to capture the original name of the variable that was passed in? I can't think of a legitimate reason to need to know that. – Brent Stewart Mar 08 '13 at 14:25
  • I am creating a library that needs to know the original name of a property for parameter validation in the case that exceptions need to be thrown. I want to be able to include that original name in the exception that is raised. – lehn0058 Mar 08 '13 at 14:27
  • What are you going to print if the user calls `MyMethod(intProperty+2)`? – Sergey Kalinichenko Mar 08 '13 at 18:25

2 Answers2

1

You cannot do it for properties, but you can do it for property-like getter methods. Starting with C#3.0, you can build delegates implicitly using method groups:

public void MyMethod(Func<int> expression) {
    // Does work
}
public int GetProperty() {
    return 123;
}
pubic void Test() {
    MyMethod(GetProperty /* NO PARENTHESES HERE!!! */);
}

Dropping the parentheses after the method name converts an invocation expression into a method group. Unfortunately, this means that there is no comparable syntax for properties, because accessing properties does not require parentheses.

Community
  • 1
  • 1
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • I've posted another answer like this before but get downvoted. After OP revised, I post a new answer. – Ken Kin Mar 08 '13 at 14:33
  • @KenKin I do not know who downvoted your first answer, but I doubt that it had to do with the substance of your answer: the content is absolutely correct. What might have triggered a downvote was lack of explanation in what you have posted: not everyone with the right to vote knows about method groups :) – Sergey Kalinichenko Mar 08 '13 at 14:38
0

Using expressions

You mentioned that it doesn't matter if the method signature has to change. So why not change the method signature to:

public void MyMethod<T>(T source, Expression<Func<T, int>> expression)
{
    // Evaluate expression
}

MyMethod(this, x => x.property);

I won't go into too much detail here on parsing expression trees, but for more information, see this question on SO:

Retrieving Property name from lambda expression

Using reflection

You can use reflection to get information about the property as well. Drop the source parameter if you don't need to get the actual value of the property.

public void MyMethod(object source, string propertyName)
{
    var pi = source.GetType().GetProperty(propertyName);
    if (pi == null)
    {
        throw new Exception("property not found");
    }

    MyMethod(source, pi);
}

public void MyMethod(object source, PropertyInfo property)
{
    // Evaluate property
}

MyMethod(this, "Property");
Community
  • 1
  • 1
p.s.w.g
  • 146,324
  • 30
  • 291
  • 331
  • As noted in the question, I want to be able to get additional information about the original property, such as the original name. This can be done by passing in functions. – lehn0058 Mar 08 '13 at 14:00
  • @lehn0058 Sorry I wasn't sure if that was what you meant. I've updated my answer to something that should be more useful to you. – p.s.w.g Mar 08 '13 at 14:09
  • This might be closer. There is still the lambda call when using MyMethod, which the end goal is to remove. However, I was thinking that using Expression might be able to achieve this somehow. – lehn0058 Mar 08 '13 at 14:13
  • @lehn0058 I added a note on reflection that might help you out. – p.s.w.g Mar 08 '13 at 14:18
  • If I use reflection at that level, I will get the information about the property inside of MyMethod. I need to keep the information about the original property that was passed into MyMethod. I will update the question to specify this explicitly. – lehn0058 Mar 08 '13 at 14:22