I need to filter the ObservableCollection using LINQ Where clause in my Silverlight application.
The object type is dynamically created using method provided in following url. http://mironabramson.com/blog/post/2008/06/Create-you-own-new-Type-and-use-it-on-run-time-(C).aspx
Is filtering my collection using Where clause for specific property possible?
How can I achieve it?
Thanks
As you know the element type of your collection only at run time it probably is object
at compile time. So the argument to the .Where
method has to be a Func<object, bool>
.
Here's a piece of code that will create such a delegate given a property of the actual element type and a lambda expression on the property (which i suppose you know the type of):
/// <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();
}
Sample usage:
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 }