Udostępnij za pośrednictwem


Acme Code Corp.

One of the major missing features in the 1.0 and 1.1 .NET Framework was generics (similar to "templates" in C++, though with important differences). The other day, Jim and I were discussing how to best approach the new set of Visual Studio Team Foundation Version Control automated UI tests and what sort of class heirarchy we want. Our decision was that we want a few helper classes which can be instantiated as needed to drive the multitude of dialogs we test. All of these helpers should have a few elements in common so that we know what we can expect from them.

In particular, we wanted a "Submit" method (performs the default action on the dialog), a "Cancel" method that takes the way to cancel (click cancel, click the close box, alt-F4, or the escape key), a "Help" method that takes its access method (F1, menu bar button), and a property that exposes the underlying dialog object, if active. This is starting to sound like an interface, yes? Well, the one problem was that each dialog has its own class, and some are dialogs, some are toolwindows, and some are actually just parts of other windows. Since we want to return a fully-typed reference from the property to avoid casting issues later on, this started to look a little hairy.

The simple solution was "generics". Here's the relevant code:

    interface IBase_DialogHelper<T>    {        T InnerDialog        {            get;        }        ...    }

Then, in our actual helper code:

    class Checkout_DialogHelper : IBase_DialogHelper<TeamFoundationCheckOutDialog>    {        public TeamFoundationCheckOutDialog InnerDialog        {            get             {                ...             }        }        ...    }

Pretty darn simple, if you ask me, and a much needed addition. And this way, no one will ever try to cast the test code  TeamFoundationCheckOutDialog class to a TeamFoundationResolveWizard, thus bringing on the end times and ending the age of wonders.