Yesterday my colleague asked me if I knew a way to run LINQ queries with externally defined expressions against queryable objects in Silverlight 4.0. What he was after could look like this:
// Some expression in string format
var expression = "Price > 10 and Name != \"Fork\"";
// Iterate target collection and filter with string expression
foreach (var product in this.Products.AsQueryable().Where(expression))
{
// ObservableCollection<Product> that is bound to the UI
this.FilteredProducts.Add(product);
}
I remembered that Microsoft’s Dynamic LINQ extension can be used to handle that kind of needs in non-Silverlight applications. The Dynamic LINQ library for C# can be downloaded here and the DynamicQuery can be found at \LinqSamples\DynamicQuery directory. I also remembered that there are some issues that makes using the same implementation a bit challenging in Silverlight. The problem is that Silverlight doesn’t have all the needed classes implemented from System.Threading namespace.
After googling a bit I found this. This solution spared my time since I didn’t need to start moving the ReaderWriterLock and other classes that were needed for the Silverlight. Cheers. So, now we have all the needed code to get Dynamic LINQ to work in Silverlight environment, but how to actually use it? Here is a simple example that should get you going.
I used test entity called Product with some simple properties:
// Simple demo entity for testing
public class Product
{
public string Name { get; set; }
public int AmountInStore { get; set; }
public bool IsAvailable
{
get { return this.AmountInStore > 0; }
}
public double Price { get; set; }
}
And then I added this to the code behind of the MainPage.xaml.
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Linq.Dynamic;
using System.Windows;
using System.Windows.Controls;
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
// Create mock data
this.Products = new List<Product>
{
new Product { Name = "Hammer", Price = 20.00d, AmountInStore = 10 },
new Product { Name = "Knife", Price = 10.00d, AmountInStore = 1 },
new Product { Name = "Pan", Price = 18.99d, AmountInStore = 100 },
new Product { Name = "Pen", Price = 1.20d, AmountInStore = 50 },
new Product { Name = "Bicycle", Price = 299.00d, AmountInStore = 15 },
new Product { Name = "Fork", Price = 0.50d, AmountInStore = 1000 }
};
this.FilteredProducts = new ObservableCollection<Product>(this.Products);
this.DataContext = this;
}
// Demonstrates data collection
public List<Product> Products { get; private set; }
// Filtered collection that is bound to the UI
public ObservableCollection<Product> FilteredProducts { get; set; }
// Testing how the querying is working.
private void FilterButtonClick(object sender, RoutedEventArgs e)
{
var expression = this.ExpressionField.Text;
if (string.IsNullOrEmpty(expression))
{
this.FilteredProducts.Clear();
this.Products.ForEach(x => this.FilteredProducts.Add(x));
}
else
{
this.FilteredProducts.Clear();
foreach (var product in this.Products.AsQueryable().Where(expression))
{
this.FilteredProducts.Add(product);
}
}
}
}
Remember to add System.Linq.Dynamic namespace to get extension rolling.
references:


