Brendan Hill
Brendan Hill

Reputation: 3752

How can I return model property from lambda expression (like MVC's "Html.TextBoxFor(xxx)")?

In MVC you can say:

Html.TextBoxFor(m => m.FirstName)

This means you're passing the model property as the parameter (not the value), so MVC can get metadata and so on.

I'm trying to do a similar thing in a C# WinForms project and can't work out how. Basically I have a set of bool properties in a User Control, and I'd like to enumerate them in a dictionary for easier access:

public bool ShowView { get; set; }
public bool ShowEdit { get; set; }
public bool ShowAdd { get; set; }
public bool ShowDelete { get; set; }
public bool ShowCancel { get; set; }
public bool ShowArchive { get; set; }
public bool ShowPrint { get; set; }

Somehow I'd like to define a Dictionary object with Enum Actions as the key, and the property as the value:

public Dictionary<Actions, ***Lambda magic***> ShowActionProperties = new Dictionary<Actions,***Lambda magic***> () {
    { Actions.View, () => this.ShowView }
    { Actions.Edit, () => this.ShowEdit }
    { Actions.Add, () => this.ShowAdd}
    { Actions.Delete, () => this.ShowDelete }
    { Actions.Archive, () => this.ShowArchive }
    { Actions.Cancel, () => this.ShowCancel }
    { Actions.Print, () => this.ShowPrint }
}

I need to be passing the property, not the property value, into the dictionary as they may change at runtime.

Ideas?

-Brendan

Upvotes: 1

Views: 903

Answers (2)

Nick Butler
Nick Butler

Reputation: 24433

All your examples have no input parameters and return a bool, so you can just use:

Dictionary<Actions, Func<bool>>

You can then evaluate the lambdas to get the runtime values of the properties:

Func<bool> fn = ShowActionProperties[ Actions.View ];
bool show = fn();

Upvotes: 3

JerKimball
JerKimball

Reputation: 16934

Ever heard of Expression Trees? Charlie Calvert's Intro on Expression Trees

Let's say you want to define a method that takes a reference to a string property; one way you could do this would be to have a method:

public string TakeAProperty(Expression<Func<string>> stringReturningExpression)
{
    Func<string> func = stringReturningExpression.Compile();
    return func();
}

Which you could then call via:

void Main()
{
    var foo = new Foo() { StringProperty = "Hello!" };
    Console.WriteLine(TakeAProperty(() => foo.StringProperty));
}

public class Foo
{
    public string StringProperty {get; set;}
}

Expression Trees let you do FAR FAR more than this, however; I heartily recommend doing some research there. :)

EDIT: another example

public Func<Foo,string> FetchAProperty(Expression<Func<Foo,string>> expression)
{
    // of course, this is the simplest use case possible
    return expression.Compile();
}

void Main()
{
    var foo = new Foo() { StringProperty = "Hello!" };
    Func<Foo,string> fetcher = FetchAProperty(f => f.StringProperty);
    Console.WriteLine(fetcher(foo));
}

More reference links:

Expression trees and lambda decomposition

A CodeProject tutorial on Expression Trees

Using Expression Trees in your API

The Amazing Bart de Smet on Expression Trees

Upvotes: 2

Related Questions