|
Since I put up the source code to CLINQ yesterday on CodePlex, I've already had multiple requests for demo code. I have a couple of tweaks left to make on the source code, but the demo will be available shortly. Here is the lowdown on the demo:
To illustrate the power of using CLINQ to do dynamic filtering (it does sorting and grouping as well, but I'll do those in another demo), I created a sample WPF application that is listening for network messages on a peer mesh. These messages are, hypothetically, coming from an order system broadcasting that employee X has created an order for Y quantity of Z product in warehouse W. The WPF listening application has two visible "bins" or "baskets" into which network-transmitted orders will be placed. The contents of these bins are determined at runtime by a configuration file. If you remember that I say peer mesh, you might gather that you could run multiple instances of this app in multiple locations on your network, monitoring any number of bins/order destinations for fulfillment. Again, this is just a cheesy sample, but it does illustrate Continuous queries on Continuous Collections that are being filled in the background from network messages.
Here's what the queries look like in the constructor of the main window of the WPF client application:
// this is a facade/model object to facilitate easy binding.
// It has 2 properies representing the bins
_binSplit = new BinSplit();
_binSplit.LeftBin = from tx in ModelRoot.Current.AllTransactions
where tx.WarehouseName == ConfigurationManager.AppSettings["leftBin"]
select tx;
_binSplit.RightBin = from tx in ModelRoot.Current.AllTransactions
where tx.WarehouseName == ConfigurationManager.AppSettings["rightBin"]
select tx;
this.DataContext = _binSplit; // bind the WPF GUI to the model object
This is really the crucial core of what it looks like to be consuming the CLINQ library. First off, you're writing queries against data that is known to be empty. When was the last time you wrote a query against an empty list and found that useful? Because these queries are continuous, it makes no difference whether any rows match your query at definition time - they could auto-populate at a later time when the app is running.
To show you that I'm not doing any manual filtering, here is the code that responds to network messages:
void _txService_OnTransactionArrived(Transaction t)
{
ModelRoot.Current.AllTransactions.Add(t);
}
Because WPF responds to INotifyPropertyChanged and the INotifyCollectionChanged events, it will respond to changes to the output of a CLINQ query. In short, when you bind your WPF GUI to a ContinuousCollection that was created through a Continuous Query - you're basically done. As changes occur in the source collection (in our case ModelRoot.Current.AllTransactions). those changes are processed by the chain of view adapters and eventually (if applicable), make their way directly to the GUI.
Here's a look at the WPF application that is receiving network messages. In the demo, I've got it listening for messages for WAREHOUSE1 and WAREHOUSE2, which are the left and right bins respectively.

The application is actually receiving network messages for three different warehouses, but because of the nature of the CLINQ queries, it is only binding to two of those. You can see how this can be used to dramatically reduce the UI-thread traffic by filtering messages to only those that are applicable to the GUI at that moment.
There are a couple of things you will need in order to run this demo:
I will be publishing more demos of CLINQ illustrating different queries and hopefully, different practical situations in which you might want to use it. If you have ideas for different kinds of demos that you want to see, also please let me know by commenting here or posting a discussion thread up on the CodePlex site.
Note: When you're running the demo, it is possible that the network sender console application will send as many as 10 batches of messages before the WPF client receives them... That's just due to the fact that the console application starts a crapload faster than the WPF application... Give it at least 15-20 seconds before the WPF app catches up and starts getting the network messages.
Hey, On the Clinq sample - I had an side comment related to your use of
DuplexChannels...
CommunicationCenter<ITransactionServiceChannel, LocalTransactionService>.OpenPeerChannel(
"urn://topic/netfilterdemo");
Console.WriteLine("Published Transaction.");