Sunday, September 27, 2009

How to change event hanlders at run time

One of the challenges when using event handlers at run time , in my opinion , is that we can't manage previously registered event handlers very easily . I mean we don't know who else is listening to the same event.

Suppose we have two combo boxes and a list box.We want to let the user select a category in first combo box and select an object in second combo box and see a list of related information of that object in the list box.

User selects Music category from category combo box.
User selects "Abby Road" from objects comb box.
A list of album information is shown to him.

Here's the source:

private void CategorySelected(object sender,EventArgs e)
{
if(
((Categroy)_categoryComboBox.SelectedItem).Type==
CategroyType.Music
)
{
_itemComboBox.DataSource=_application.GetMusicAlbums();
}
}

private void ItemSelected(object sender,EventArgs e)
{

if(_itemComboBox.SelectedItem is MusicAlbum)
{
_list.DataSource=
_application.
GetMusicAlbumAdditionalInfo
((MusicAlbum)_itemComboBox.SelectedItem);
}
}


Well it's working but it's not very nice. As you can see we should write a lot of "if" to handle different kind of categories and objects.
OK we could change the event handler instead of using if.
Suppose that we have registered some event handlers in a dictionary then we can write :

_itemComboBox.SelectedItemChanged+=
_eventhandlersRegistry[selectedCategory.Type];



But we have a little problem : what if there's already a category selected ? so we should first remove last SelectedItemChanged event handler then we have to write:

_itemComboBox.SelectedItemChanged-=
_lastSelectedItemChangedEventHandler
_itemComboBox.SelectedItemChanged+=
_eventhandlersRegistry[selectedCategory.Type];
_lastSelectedItemChangedEventHandler=
_eventhandlersRegistry[selectedCategory.Type];


To solve this kind of scenario , I recently use a solution that I'd like to share with you:
I use a nested EventHandler delegate therefore there's no need to change the event handler of actual event .Here's what I do:
I have an event handler delegate declared as :

private EventHandler _nestedSelectedItemChangedEventHandler



Then I have this general event handler for the actual event :

_itemComboBox.SeletedItemChanged+=
GeneralItemChangedEventHandler;



When the category is changed I place a new delegate in my nested event handler like this:

_nestedSelectedItemChangedEventHandler=
_registeredEventHandlers[_selectedCategory.Type];


and GeneralItemChangedEventHandler will call nested event handler as follows:

private void GeneralItemChangedEventHandler (object sender,EventArgs e)
{
if(_nestedSelectedItemChangedEventHandler!=null)
_nestedSelectedItemChangedEventHandler(sender,e);
}



This approach can be used if you are implementing a strategy pattern so that you want to change the behavior by changing the state of your object and there's always a single event handler involved to handle an event.

Monday, September 21, 2009

Using generic methods to avoid boxing-unboxing

Every time we convert a value type (int,decimal,double,etc) to a reference type (to an object to be specific) a boxing occurs (As MSDN define it , it means to put a value type inside heap) and if we convert an object to an int , an unboxing occurs. Here's an article on MSDN that describes it all.
I'm working on this method that gets a DataRow ,a FieldName and a default value and returns row[fieldname] value (if value is null or DBNull it returns the default value)
My first vesrion of this method is something like this:

public static string GetFieldValue
(DataRow row,
string
fieldname,
string defaultvalue)
{
var value=row[fieldname];
if(value==null || value==DBNull.Value)

return defaultvalue;
return value;
}



Later ,I want to write an overload for this method to work with int values I write something like this:

public static int GetFieldValue
(DataRow row,
string fieldname,
int defaultvalue)
{
var value=row[fieldname];
if(value==null || value==DBNull.Value)

return defaultvalue;
return (int)value;
}



OK an unboxing is happening here and I can't do anything about it.
I think to myself here we have a sign of DRY violation .I can have a single method as a base,something like this:

public static object GetFieldValue
(DataRow row,
string
fieldname,
object fieldvalue)
{
var value=row[fieldname];
if(value==null || value==DBNull.Value)
return defaultvalue;
return value;
}
Then I can rewrite the int version like this:

public static int GetFieldValue
(DataRow row,
string fieldname,
int defaultvalue)
{
return (int)GetFieldValue(row,fieldname,(object) defaultvalue);
}
But wait a second, I can see a boxing here which is not necessary but how can I get rid of it?
One solution that comes to my mind is to change my base method to a generic method:

public static
T GetFieldValue<T>
(DataRow row,
string fieldname,
T defaultValue)
{
var value=row[fieldname];
if(value==null || value==DBNull.Value)
return defaultvalue;
return (T)value;
}



Again if T is a value type an unboxing will occur but there's no boxing and I can rewrite the int version as :

public static int GetFieldValue
(DataRow row,
string fieldname,
int defaultvalue)
{
return GetFieldValue<int>(row,fieldname, defaultvalue);
}

I wrote a test that ran each method for 1,000,000 times and it turns out that the omitted boxing impact is very small.(418 ms for object version vs. 358 ms for generic version)

Saturday, September 19, 2009

A Custom linq query builder

In my opinion one the most interesting features of Linq is Expression Trees.They let us build structured queries over IQueryable type.
IQueryable ,as its name implies, is an interface that let us build a query over a provided object of type T.Although IQueryable and expression trees are mostly used in Linq to sql but since every IEnumerable can be converted to an IQueryable object (using System.Linq.AsQueryable method) these great tools are available to every kind of Linq (linq to Xml and linq to objects for example).
When we build an expression tree over an IQueryable object , the expression itself won't be executed until we really want to get the data.
For example if we write the following code:
(DataSource is an IQueryable object)

var result=DataSource.Where(post=>post.Title.IndexOf("Linq")>0);




result is yet another IQueryable that you can query again :

result=result.Where(post=>post.CreationDate>new DateTime(2009,1,1));




Now if we've added all we wanted to our query we can execute it either by converting the result to an ICollection (a List or an array for example) or by executing GetEnumrator method ( usually by using a for each loop).

Based on this introduction I designed a custom query builder that facilitate querying an object using collected search arguments (in a windows /web form for example)

Here's the scenario that I had in mind :
There's a web/win form that lets a user fill-in some information about what he wants to see.
Consider a blog application , a user can search post based on their titles and/or their creation date.Therefore a QueryPostArgs object is created and populated using the information provided by user.
Then this object is passed to a QueryBuilder to build a query from it.Query builder contains some register query methods and when is asked to build the query it will use them to build the final query.
Enough talking let write some code :

To collect and transfer the arguments information we have an AbstractQueryArgs class.

public abstract class AbstractQueryArgs<t> where T :class
{
}




To build queries over a post object we then derived from it and create a PostQueryArgs class.

public class PostQueryArgs : AbstractQueryArgs<post>
{
public PostQueryArgs()
{
CreationDateFrom = DateTime.MinValue;
CreationDateTo = DateTime.MaxValue;
}
public string Title { get; set; }
public DateTime CreationDateFrom { get; set; }
public DateTime CreationDateTo { get; set; }
public string[] Tags { get; set; }
}



To build query using an AbstractQueryArgs we have an AbstractQueryBuilder like this:

public abstract class AbstractQueryBuilder<t,tsearchargs> 
where
T :class where TSearchArgs :AbstractQueryArgs<t>
{
protected delegate IQueryable<t>
QueryMethodDelegate
(IQueryable<t> queryable,TSearchArgs searchArgs);

public IQueryable<t> DataSource { get; private set; }
private readonly List<QueryMethodDelegate>
_queryMethodDelegates = new List<QueryMethodDelegate>();


protected AbstractQueryBuilder(IQueryable<t> dataSource)
{
DataSource = dataSource;
}


protected void AddQueryMethod(QueryMethodDelegate queryMethodDelegate)
{
_queryMethodDelegates.Add(queryMethodDelegate);
}
public IQueryable<t> Build(TSearchArgs searchArgs)
{
var queryable = DataSource
foreach (var queryMethodDelegate in _queryMethodDelegates)
{
queryable=queryMethodDelegate(queryable,searchArgs);
}

return queryable;
}
}



It allow us to build custom query builders for any T class.As you can see it gets an
IQueryable as its data source via constructor.Then we can add some query methods to a list of query methods . A query method is any method that gets an IQueryable and a query arguments object and returns an IQueryable (It somehow a visitor method that visits an IQueryable object and do something on it based on provided query arguments and return it back ) To define a query method a protected delegate is defined.Every class that is derived from this abstract class can add its custom query methods to the query methods list using AddQueryMethod protected method.
Finally there's this Build method that build an IQueryable object using the provided datasource and passing it to each query method.As you can see this method is also returning an IQueryable object that lets us to perform any further queries over it if necessary.

Now we can create our custom query builder for our post object as follows:

public class PostQueryBuilder:AbstractQueryBuilder<post,postqueryargs>
{
public PostQueryBuilder(IQueryable<post> dataSource) : base(dataSource)
{
AddQueryMethod(AddTitleExpression);
AddQueryMethod(AddCreationDateExpression);
AddQueryMethod(ContainsAllTags);
}

private static IQueryable<post>
ContainsAllTags(IQueryable<post> queryable , PostQueryArgs queryArgs)
{
if (queryArgs.Tags == null || queryArgs.Tags.Length == 0) return queryable;
return queryable.Where
(x => x.Tags.Intersect(queryArgs.Tags).Count() == queryArgs.Tags.Length);
}

private static IQueryable<post>
AddTitleExpression(IQueryable<post> queryable,PostQueryArgs queryArgs)
{
return string.IsNullOrEmpty(queryArgs.Title) ? queryable :
queryable.Where(x=>x.Title.IndexOf(queryArgs.Title)!=0);
}

private static IQueryable<post>
AddCreationDateExpression(IQueryable<post> queryable,
PostQueryArgs queryArgs)
{

return queryable.Where(
x => x.CreationDate >= queryArgs.CreationDateFrom &&
x.CreationDate <= queryArgs.CreationDateTo); }


As you can see this class add three query methods to query methods list.One for title,one for creation date and one for tags.

Now that we have created these classes , all we need to do to build a query on a post datasource is like this:

var posts=new []{_post1,_post2,_post3};
var queryBuilder=new PostQueryBuilder(posts);

var queryArgs=new PostQueryArgs{Title="Intro",Tags=new []{"C#","Linq"}};
var query=queryBuilder.Buid(queryArgs);




Then we have a IQeryable object that when we try to enumerate it , post objects with "Intro" in their title and containing "C#" and "Linq" tags will be returned.

P.S. I have upload the source code in codeproject site you can fint it here.