0

Normally in lamda a expression such as (x => x.FirstName) the lamda would return the value of "FirstName" (presumably a string) but some how @Html.TextBoxFor(x => x.FirstName) knows that I am referring to the property "FirstName" and not the value returned by FirstName. What C# or compiler technique is being used for achieve this? I tried reading through the MVC source code but it went over my head.

  • I don't understand what you're asking here? – stuartd Oct 25 '19 at 23:46
  • 1
    Simply put, it parses the lambda expression to see what property is being referenced. – John Wu Oct 25 '19 at 23:46
  • TextBoxFor receives an Expression, rather than a Func ( https://learn.microsoft.com/en-us/dotnet/api/system.web.mvc.html.inputextensions.textboxfor?view=aspnet-mvc-5.2) .. checkout this answer https://stackoverflow.com/questions/793571/why-would-you-use-expressionfunct-rather-than-funct on func vs expression – KMoussa Oct 25 '19 at 23:54
  • This sort of question makes me think this is an [XY Problem](https://meta.stackexchange.com/q/66377/226912). Is there a different problem you're having and are attempting to handle by implementing this behavior? And are thus looking for guidance in that respect? – Brett Caswell Oct 25 '19 at 23:55
  • I am new to ASP.Net MVC and while reading a chapter on helper methods I couldn't wrap my head around how the compiler was determining the difference between the reference to the property vs it's return value. John Wu's answer below fixed me right up. –  Oct 26 '19 at 01:21

1 Answers1

0

An Expression is just an object representing what is contained in the lambda expression. It can be inspected like any other object. You can think of it as a complicated sort of Reflection, and indeed you can get things like Type and PropertyInfo for anything inside it, if you know how to parse it.

This example demonstrates how a simple expression like m => m.FirstName can be parsed to find out what property is being referenced:

public class MyModel
{
    public string FirstName { get { return "John Jacob Jingleheimer Schmidt"; } }
}

public class Program
{
    public static void Main()
    {
        var model = new MyModel();
        var result = Test(m => m.FirstName, model);

        Console.WriteLine(result);
    }

    public static TOut Test<TIn, TOut>(Expression<Func<TIn, TOut>> expression, TIn instance) where TOut: class
    {
        MemberExpression memberExpression = (MemberExpression)expression.Body;
        var member = memberExpression.Member;

        Console.WriteLine("The expression is a reference to '{0}.{1}'", member.DeclaringType.FullName, member.Name);

        var compiled = expression.Compile();
        var result = compiled(instance) as TOut;
        return result;
    }
}

Output:

The expression is a reference to 'Example.MyModel.FirstName'
John Jacob Jingleheimer Schmidt

Link to DotNetFiddle demo

John Wu
  • 50,556
  • 8
  • 44
  • 80
  • Thank you, I was missing that the lamba was inside an Expression object and how Expression object works. –  Oct 26 '19 at 01:23