How to filter a collection with a dynamically formed type using the LINQ where clause

dynamic-linq linq linq-to-objects observablecollection silverlight-4.0

Question

In my Silverlight application, I must use a LINQ Where clause to filter the ObservableCollection.

The procedure described in the following url is used to dynamically build the object type. http://mironabramson.com/blog/post/2008/06/Create-you-own-new-Type-and-use-it-on-run-time-(C).aspx

Is it feasible to use the Where clause to filter my collection for a certain property?

How can I do that?

Thanks

1
0
11/6/2011 7:35:56 AM

Popular Answer

Due to the fact that you only know the element type of your collection at run time, it probably is.object during compilation. The argument hence to the.Where technique must be aFunc<object, bool> .

Given a property of the real element type and a lambda expression on the property (which type I assume you are aware of), the following code will produce such a delegate:

/// <summary>
/// Get a predicate for a property on a parent element.
/// </summary>
/// <param name="property">The property of the parent element to get the value for.</param>
/// <param name="propertyPredicate">The predicate on the property value.</param>
static Func<object, bool> GetPredicate<TProperty>(PropertyInfo property, Expression<Func<TProperty, bool>> propertyPredicate)
{
    if (property.PropertyType != typeof(TProperty)) throw new ArgumentException("Bad property type.");

    var pObj = Expression.Parameter(typeof(object), "obj");

    // ((elementType)obj).property;
    var xGetPropertyValue = Expression.Property(Expression.Convert(pObj, property.DeclaringType), property);

    var pProperty = propertyPredicate.Parameters[0];
    // obj => { var pProperty = xGetPropertyValue; return propertyPredicate.Body; };
    var lambda = Expression.Lambda<Func<object, bool>>(Expression.Block(new[] { pProperty }, Expression.Assign(pProperty, xGetPropertyValue), propertyPredicate.Body), pObj);
    return lambda.Compile();
}

Example of use:

var items = new List<object> { new { A = 0, B = "Foo" }, new { A = 1, B = "Bar" }, new { A = 2, B = "FooBar" } };
var elementType = items[0].GetType();

Console.WriteLine("Items where A >= 1:");
foreach (var item in items.Where(GetPredicate<int>(elementType.GetProperty("A"), a => a >= 1)))
    Console.WriteLine(item);

Console.WriteLine();
Console.WriteLine("Items where B starts with \"Foo\":");
foreach (var item in items.Where(GetPredicate<string>(elementType.GetProperty("B"), b => b.StartsWith("Foo"))))
    Console.WriteLine(item);

Output:

Items where A >= 1:
{ A = 1, B = Bar }
{ A = 2, B = FooBar }

Items where B starts with "Foo":
{ A = 0, B = Foo }
{ A = 2, B = FooBar }
0
7/26/2017 10:06:26 AM


Related Questions





Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow