Expression<Func<TModel,TProperty>> as Property for object initialization?
Asked Answered
A

2

6

My expression aren't great and I would like to improve on them so I am wondering if someone could explain for me if it possible to create a property in a class that can be given a value during instantiation like this:

new Column<Product>{ ColumnProperty = p => p.Title};

or better still (but I think I am pushing it)

new Column {ColumnProperty = p => p.Title};

with a class something like this:

public class Column<TModel>
{
        public Expression<Func<TModel, TProperty>> ColumnProperty { get; set; }
}

The basic idea behind it is that I create a Grid from a bunch of Column objects something like this.

List<Product> productList = GetProductsFromDb();
List<Column> columnList = new List<Column>();

columnList.Add(new Column<Product> {ColumnProperty = p => p.ProductId, Heading = "Product Id"});
columnList.Add(new Column<Product> {ColumnProperty = p => p.Title, Heading = "Title"});

Grid myGrid = new Grid(productList, columnList);

This may not be the tidiest/easiest way to do this but I am interested in knowing whether it can be done as I want to improve my understanding of expressions and I love being able to have strongly typed values instead of string literals it's so much nicer to work with.

Any thoughts, ideas, ramblings would be greatly appreciated

Cheers Rob

Akim answered 22/11, 2010 at 10:56 Comment(0)
G
9

When you define something like Func<TModel, TProperty> it means there is a method that takes a TModel type and returns a TProperty type. So lambda expressions like

p => p.ProductId 

returns the value of the property rather than the property itself.

What you can do to make this syntax work is to define your ColumnProperty as follows:

public Expression<Func<TModel, object>> ColumnProperty { get; set; }

Then you can extract detailed information from the expression tree.

Gadgeteer answered 22/11, 2010 at 11:22 Comment(2)
Hey idursun - thanks this works too - I used dynamic instead of object but the result is the sameAkim
object will result in an exception when used for primitive values (e.g. int). Using dynamic works in all casesToadfish
A
1

Ok so I just had a brainwave and changed TProperty to dynamic and I can now do this so I guess I answered my own question but would be keen on other peoples thoughts about the pros/cons of this approach:

foreach(Product p in productList)
{
    var value = column.ColumnProperty.Compile().Invoke(p);
}

In fact

if I change my property to

public Func<TModel, dynamic> ColumnProperty { get; set; }

I can just do:

foreach(Product p in productList)
{
    var value = column.ColumnProperty(p);
}
Akim answered 22/11, 2010 at 11:21 Comment(1)
The expression approach is a decent approach. I think that dynamic requires a bit more overhead but may prove to have a negligible impact. A dynamic object maintains a dictionary of object members behind the scenes.Naxos

© 2022 - 2024 — McMap. All rights reserved.