Combining expressions in an expression tree using lambda syntax

Viewed 104

I am building a service that retrieves Enum-like instances from various repositories. The repositories store the data differently, but all can be retrieved into an EnumEntry { int Id; string Name; } class.

My idea is to use a base class that takes Func delegates as selectors to identify the Id and Name fields on each underlying repository record. e.g.

// constructor:
BaseEnumService<T>(Table<T> table, 
                   Expression<Func<T, int>> idSelector, 
                   Expression<Func<T, string>> nameSelector) {... }

// usage
var caseCategoryService = new BaseEnumService(CaseCategoriesTable, x => x.id, x => x.category)

So far so good.

To retrieve an EnumEntry, given that idSelector and nameSelector are Expressions of pure functions, I thought I could use a lambda expression like this and the compiler would figure it all out:

table.Select(x => new EnumEntry() { Id = idSelector(x), Name = nameSelector(x) }).ToList();

...but the database IQueryable implementation complains as it does not like 'external' functions.

Combining everything with expression trees works ok, e.g.

var record = Expression.Parameter(typeof(T));
 Expression<Func<int, string, EnumEntry>> createEnumExpression = (id, name) => new EnumEntry() { Id = id, Name = name };
var selectExpression = Expression.Invoke(createEnumExpression,
                Expression.Invoke(idSelector, record),
                Expression.Invoke(nameSelector, record));

return table.Select(Expression.Lambda<Func<T, EnumEntry>>(selectExpression, record));

.. but this seems rather verbose and ugly for something so simple.

Is there no way to combine Expression<>s using lambda syntax in the way I originally tried?

0 Answers
Related