Wednesday, November 02, 2005

Provider Model

I have been on a mission in my day-to-day grind lately, a mission to fully explore the .NET Provider Model Design Pattern. I spent an inordinate amount of time last week creating a simple little class to serve up icons, extensions, file associations and pseudo-dynamic application-specific file identifers just so I could bind it to the output I often get after translating our documents to HTML, or uploading documents for storage and display, while leaving it open enough that other applications could use their own file identifiers in the same structure. When I really got moving on it, I decided that it would be my first real candidate to fulfill the new enterprise-wide push to make code reusable. It was at this point that what should have been simply a well-formed XML document became a model in how far you can go with your code. I wrote and rewrote until I had a factory that examined the incoming connection string and based on a best guess, served up either an XML file, XML HTTP, SQL or Oracle version of the object, with the option to create others. However, it relied on always feeding it a connection during creation and exhibited several behaviors that were more for convenience than good programming (for instance, I wasn't entirely sure how to cache the return object correctly before it was returned so that I didn't hit the database twice when once was sufficient). Enter the Microsoft .NET Provider Model, a new model they're pushing for .NET 2.0 which will be baked into the framework, particularly as regards the membership classes. Basically, you have a provider object, and then your other objects inherit from this object to force overrides on common functionality. Another object then handles the instance creation of the type of provider you want and hands off appropriate functions to that object if it's already cached. Pretty straight forward, but it's based on the idea that there will be improvements in 2.0 - generics, etc. I didn't have any of those. What I had was lots of implementation that I didn't want to repeat over and over and an example for .NET 1.1 that didn't really facilitate an implementation model or my need for version 1.1 collections instead of individual items (I don't need one membership item, I need 10-100 file items). So I rewrote. And discovered that the example only supported one parameter constructors. So I rewrote (with some advice from the Hairy Swede). And learned that the total deconstruction of all items and providers into separate assemblies meant that Type.GetType didn't work at all unless you loaded the assembly by namespace and assembly, and while you're at it, you need the culture and version - which simply weren't available if you're trying to load by name. So you have to make a separate little application to load up each of the providers and dump you their full assembly name so you can cut it and paste it back into the web.config. So I rewrote. And learned that my collection inheritance from my other project wouldn't work at all as I'm not coding in C and only get to inherit from one object. I needed an interface. So I rewrote. I added an (array)List and used my other functions, only to find out that it wouldn't bind. It needed an IList interface so that I could get an enumerator. So I rewrote. End result - a completely reusable file identifier collection that can be rebound to any data source (but currently four) across (currently) two constructors. Seven projects, including the harness, and approximately 12 classes, all to do exactly what can be accomplished by just strapping my UI objects to source XML (except for a little base64 to icon conversion piece that I added for fun because I had the code).

I can see the benefit if you have objects with a lot of functionality (not just one or two functions like mine) and there is a strong possibility that you might have to switch between data providers or might want to roll over if one fails or if you're providing the code to an actual paying customer and want the ability to just hand them an assembly for mySQL, Active Directory or Access without rewriting any code - but for my little pseudo-non-profit project, it really is quite a bit of overkill.

Anyway - if you like code, it's a fascinating diversion and promises to be the model du jour in .NET programming 2.0. Here are a few helpful articles:

Provider Model Design Pattern and Specification, Part 1 - Rob Howard
Provider Design Pattern, Part 2
ASP.NET 2.0 Provider Model: Introduction to the Provider Model (120 edge of the chair pages)

4 comments:

MeanMrMustard said...

Why didn't I read this last night, when I was trying to get to sleep? Now you owe me coffee.

Steve Eck said...

Wow. A paragraph break or two in there might have been nice.

Scooter said...

I was trying to mimic the narrative in my head that went on during the coding. If you drank a cup of coffee after every sentence, you'd get a nice summary of the whole, extended event.

Steve Eck said...

I suppose. It would have been interesting to break it up everytime you rewrote something though. Just so you could see all the extra effort involved in making that resuable.

Not that there isn't a benefit in having resuable code, but it takes a lot more effort then a lot of people realize, I think.