This post is a result of an expensive lesson I
learned.
The situation: We use an MVP style architecture,
Presentation Abstraction
Control, on our application. As such the controller maintains a
reference to the view(presentation) and the model(control) via IView and IModel
references. As such any time we want to invoke a method on the model or
the view we have to do something like this:
WireViewEvents((IOrderDetailView)this.View);
I'll draw your attention to the casting that happens.
Since the controller is handling all the interaction between the view and the
rest of the application, you can imagine how this type of casting ends up in all
of our code.
We first took a stab at the casting 'problem' by
implementing a private property on the controller to take care of the
casting for us. Then we could handle the above by doing something
like:
WireViewEvents(this.PrivateView);
This works but it had a smell of hoakie-ness to
it. So I thought about trying to come up with a 'Generic'
solution. My idea was brilliant if I say so myself ;). I decided
to change the definition of the controller to be a generic controller that took
in the type of view and the type of model on creation. That way each of
the view and model properties would be strongly typed.
I proceeded to implement this in our code base since it was not
easy to just make one change. Everything compiled but once I was
done the application started throwing exceptions. It seemed that
IController<ConcreteModel, ConcreteView> could not be passed to an
instance declared as IController<IModel, IView>. Say what?!?!
At first I didn't get it. After some research, I found out that
Generics do not support covariance and contravariance.
What is covariance/contravariance? In a nutshell, they are terms used
to describe how types relate to each other. The names come from the math
world and is used to measure the degree to which two variables move up or down
together. The term has been adopted by CS geeks to describe
a situation where a derived type is used when a base type was
expected (MSDN).
The core issue has apparently been documented by the community in many details but
the short of it is that Generics are not covariant. For one of the best
write ups that I have seen on the subject, Rick Byers wrote an
article that covers it. You can see it here and
his follow up here.
Lesson learned, had I just RTFM this would have not taken me 6 hours to
learn!
References:
MSDN - http://msdn.microsoft.com/msdnmag/issues/05/10/NETMatters/
[ Currently Playing : Lonely Avenue - Taj Mahal - Phantom Blues
(03:30) ]