How to create dynamic selection in IEnumerable <T> at runtime?
Given that I have an IEnumerable<T>
, where T
is any object, how can I select a specific property from it, given that I know the name of one of the property names at run time as a string?
For example:
var externalIEnumerable = DataPassedFromConsumingCode(); // `IEnumerable<T>` string knownPropertyName = "Foo"; var fooSelect = externalIEnumerable.Select(...);
In essence, I'm obviously just doing externalIEnumerable.Select(x=> x.Foo);
but I need to execute this Select
at runtime when I have no control over its initial creation.
-
ANSWER: Based on AlanT's answer, here is what I actually did:
public Expression<Func<TItem, object>> SelectExpression<TItem>(string fieldName) { var param = Expression.Parameter(typeof(TItem), "item"); var field = Expression.Property(param, fieldName); return Expression.Lambda<Func<TItem, object>>(field, new ParameterExpression[] { param }); }
I saved this as an expression because a call to Compile
caused an IQueryable switch, which meant that the database was deleted unnecessarily. Therefore, to use it, I just do the following:
string primaryKey = _map.GetPrimaryKeys(typeof(TOriginator)).Single(); var primaryKeyExpression = SelectExpression<TOriginator>(primaryKey); var primaryKeyResults = query.Select(primaryKeyExpression).ToList();
This can be done using the expression
eg.
private class Foo { public string Bar { get; set; } } private IEnumerable<Foo> SomeFoos = new List<Foo>() { new Foo{Bar = "Jan"}, new Foo{Bar = "Feb"}, new Foo{Bar = "Mar"}, new Foo{Bar = "Apr"}, }; [TestMethod] public void GetDynamicProperty() { var expr = SelectExpression<Foo, string>("Bar"); var propValues = SomeFoos.Select(expr); Assert.IsTrue(new[] { "Jan", "Feb", "Mar", "Apr" }.SequenceEqual(propValues)); } public static Func<TItem, TField> SelectExpression<TItem, TField>(string fieldName) { var param = Expression.Parameter(typeof(TItem), "item"); var field = Expression.Property(param, fieldName); return Expression.Lambda<Func<TItem, TField>>(field, new ParameterExpression[] { param }).Compile(); }
hth
Alan.
The linq dynamic library allows you to define predicates and predictions on the fly and can suit your use case