Aug 10th 2008 08:52 am

Interface Segregation Principle, Asp.Net, Generics, Interfaces and Covariance, Oh my!

The interface segregation principle is something most asp.net developers tend to ignore. If I only have one consumer of my business layer (the web/UI layer) why bind against an interface instead of the actual business objects?

Recently at my job we found ourselves answering that question. We have a single code base and strong continuous integration. Binding to UI interfaces seemed to make things “less agile” :). Now that we’re live, however, things have changed. We’re willing to sacrifice the beautiful patterns we’ve held so dear for the pragmatic concerns of performance and scalability.

We analyzed our application for problems and began to work around some of our thornier speed issues by writing custom sql that could leverage vendor specific database features and using the caching features of the asp.net framework.

The problem is that our business entities are too heavy – these custom queries were faster in part because we didn’t need to retrieve all the data necessary to initialize an entity. Additionally, to avoid GC problems, the data we wanted to cache needed to be much “lighter” without references to other objects or data context.

Our web code was now too rigid. It was binding against strongly typed business objects and needed to bind against interfaces to give us the flexibility and control re-use we needed. We therefore adjusted the necessary Asp.net controls that bound to entities to bind to interfaces instead.

A problem arose, however, when we went to bind lists. The problem is called covariance and discussed very well here and compared with JAVA here. Basically, to optimize performance, the .net runtime emits code to strongly type collections. This new type has no ties to the interfaces or inheritance hierarchy of the type that it is templating e.g. If A is the base class of B and C, one cannot pass a List<B> to a method expecting a paramter of type List<A>.

The way around this is actually pretty simple. It’s how most asp.net controls work out of the box. A control’s datasource is simply an object. Only when DataBind() is called is the datasource consumed, and then it’s consumed item by item in the ItemDataBound event where there is no problem casting individual items of a datasource to an interface.

This paradigm works well. Though we can’t cast strongly typed generic lists based we can cast Foo to IFoo as we consume each item for databinding. The result is a more flexible UI with more code re-use and improved performance.

No Comments yet »

Trackback URI | Comments RSS

Leave a Reply

« | »