Saturday, April 28, 2007

Lack of support for generic base classes in Windows Forms designer

Just recently having started my first real life .Net 2.0 project I wanted to utilize all the cool new features in my day-to-day job. One of those features is of course the support for Generics in C#. But, as with all cool stuff, getting your hopes up to high can get you disappointed.
In our Windows forms application we use a design pattern in which a UserControl defines a callback interface which is implemented by a mediator. This makes sure we have a loose coupling between the UserControl and the source of the rest of the application.
To avoid having a lot of duplicate code I decided to make a base class that does some of the stuff related to initializing the mediator. While every control will have a different mediator interface this called for generics (sample code is written by hand, so don't mind the compiler errors).
class ViewControlBase : UserControl
 where TMediator : IMediator
{
 TMediator _mediator;

 protected TMediator Mediator
 {
  get { return _mediator; }
 }
 public InitMediator(IMediator mediator)
 {
  _mediator = (TMediator) mediator;
  // some more generic stuff
 }
}
Now the viewControls are derrived from ViewControlBase like this
class CustomerView : ViewControlBase
{
 // … Use typed access to the Mediator property
}

By using a generic base I was able to have Typed access to the Mediator in all the derived classes, and I avoided writing the initialization code over and over again. Hitting F5 proved all worked just as expected.
But when I opened one of the ViewControls in the designer the designer was filled with an error saying something was wrong. Usually this means that you have to rebuild the solution, clean up, rebuild some more and eventually it works. Not is time :-(
The error stated that the class CustomerView was not 'Designable' because it was not able to create an instance of ViewControlBase. That is true, it is however possible to create an instance of ViewControllerBase
I found a work-around (or a dirty Hack) by creating an empty dummy class like this
class CustomerView : CustomerViewDummy
{
 //…
}
class CustomerViewDummy: ViewControlBase
{}

Now CustomerView is no longer (directly) derived from a generic class the designer stops complaining and shows the control in design view as expected. Since I didn't really like this solution I went back to old-school and duplicated the same code in every control (Bummer!)

No comments:

Post a Comment