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?