Code - Type Resolution Problems

Friday, September 30, 2005

I developed a Wizard framework in C# which is laid out as follows:



The basic understanding is that there's a base form in Wizbase which is used to build wizard pages. Navigation through the wizard pages, and various other utility functions, is handled by WizardMain. I needed to be able to store an 'execution' of the wizard (user's selections on each page from beginning to end) and wanted to do so generically. Serialize the data maybe? That was my first thought. Here's the kicker: the data to be stored was in custom classes down inside the arbitrary wizard code. This is a problem because the framework is compiled without knowledge of 'arbitrary wizard' code, and thus does not have a reference to any of its classes. How then was I to serialize and deserialize Types of which I had no knowledge?

One idea was to move the code into the arbitrary wizard, which has direct references. I disliked that, as it left the work to the wizard programmer, as opposed to the framework programmer. So, I started doing tests using the BinaryFormatter. Guess what? It could serialize it to a file no problem. I assumed it used reflection to do so, and was not that surprised once I thought about it at little. So I did the deserialization code.


// deserialize the memory stream into the original object and return
BinaryFormatter binaryFormatter = new BinaryFormatter();
return binaryFormatter.Deserialize(memoryStream);


Guess what? No workie. There were numerous problems.

First, I learned the BinaryFormatter stored, along with the raw serialization, the version number, culture, etc. of the assembly from which the Type came. That meant every time I recompiled the project, that nifty little version number line in the AssemblyInfo.cs file changed the version number on me, and thus the serialized format couldn't be matched up to any classes in the running code.

Culprit 1: [assembly: AssemblyVersion("1.0.*")]

I changed the asterisk to a 1, which fixed the immediate problem, but I wasn't fond of the entire concept, so I switched to the slightly more forgiving (and hand editable) SoapFormatter. So far so good.

Next problem: Still wouldn't deserialize. File not found error. File not found? That's odd I thought. Turns out the serialized SOAP ASCII mush knew what class it was, and the CLR was trying to find the file from whence it came. Kinda neat actually. My test *.sln file had 3 projects being compiled into their own folders, so I added a post compile command line to copy the arbitrary wizard dll into the same folder as the wizardmain.exe. Guess what? It worked. Deserialization of an unreferenced type, made possible by the Type resolution of the CLR.

Om ... wait a sec. My layout, noted in the pretty Visio diagram above, reminded me that the arbitrary wizard file may not be in the same location as the WizardMain.exe. In fact, that's why the xml file exists: to tell the WizardMain where to get and load the arbitrary wizard file(s) from. Crappy. What now? The CLR can't resolve Types in assemblies in random locations on the target hard drive.

Some research lead me to understand that there's an event raised when the CLR can't resolve a type. I threw in an event hander for it:


// setup a handler for the case where the type to be resolved cannot be
// found by the CLR (ie: containing assembly is not in the current folder)

AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(FileResolveEventHandler);

And the associated handler:

public Assembly FileResolveEventHandler(object sender, ResolveEventArgs args) {}

In my code that accepts an intial call from the arbitrary wizard, I just grab the assembly location:

_CallingAssembly = Assembly.GetCallingAssembly();

And inside the event handler just above I just inserted the following single line of code:

// we previously stored a reference to the calling assembly,
// and we know we are attempting to resolve a type in that same assembly
// (some wiz file) therefore, we merely pass that reference back to the
// appdomain via this handler, and we should be good to go

return _CallingAssembly;


And we have it. The WizardMain.Exe can de/serialize unknown types, regardless of location, allowing my framework consumers to store and retrieve anything they want (assuming it has the [Serializable] tag).

Cheers!
TPC

Zievo - A New Direction In My Life

Thursday, September 29, 2005

And so the very first public and tangible aspect of our (Greg, Cory, and myself) future multi-million dollar software company has materialized. It is, none other, than a tiny slice of the web devoted to such.

Check out the zievo website!

Yes, there's really nothing there, I know. We can't rightly open up the innards until there's something to sell. However, there have been over two years pumped into our first flagship product and we are excited about releasing it into the world. That's when it's time comes of course. Alpha is just around the corner. :)

So what is the first product? It's a project management tool that fits in a mostly unfilled niche. I don't want to talk about it too much, but I'll certainly post again when we let this baby loose.

Out of the way MS Project! Time for something that helps instead of hinders!

TPC

Rant - Time Off

Tuesday, September 06, 2005

So Monday the 29th of August I was at my desk at work and it hit me ... BAM! I'm burnt out. I can't even read my own code. I go for a walk outside for a few minutes, take a few deep breaths and come back with a new perspective. From this perspective I'm about 1,000 lines of prototype code over my head for a Monday. Multi-threaded enterprise software architecture is a bitch.

So, I call my parents and book their summer cabin for a week. I email my boss and tell him I know it's short notice, but I need a week off and would appreciate his help in getting it. I write a grocery list until the approval arrives (10 mins), head home to pack (20 mins), grocery shop (20 mins), drive to the cabin (70 mins), unpack and settle in (40 mins), then nap for most of the rest of the day.

The rest of the week I spent doing whatever I wanted with a few exceptions: no food containing fat, no alcohol, and no communication with the outside world, until the upcoming Friday. How'd it go? I'm seriously a new man. I did quite a bit of time in my isolated paradise napping, lounging around in my PJ bottoms, reading (and finishing) the novels on my night table, playing my new guitar, experimenting with fat free super healthy recipes, and drinking many a cup of Tetley on our back patio overlooking the salt water harbor, at times-of-luck watching a mink jump off our wharf to fish for her and her family. Turns out they live under the cabin. No wonder I saw her so often.

It was remarkably relaxing, and amazingly productive. After two days winding down I had the NEED to code. I had both laptops with me (new and old) so I coded when I wanted to. I got more done in that 4 days than in the previous month at work, given my clarity of thought and how easily my first designs turned out to be great designs (read: good enough).

I learned something about myself. I argue with people in my head A LOT. How bad is it when you are carrying out argument scenarios while virtually isolated from society? It stopped after the wind down period. I'm not sure if that was because I noticed the affliction, or because it was a side effect of my being burnt out, but I've decided to use it in the future as an indicator. :)

So, that Friday I drove home for a bunch of reasons. First was to have lunch with a long time friend at the office (his last day) who found the courage to take his wife and 3 kids and move to Africa to do missionary work of sorts in a small school there. That's humbling courage. Later that day Nicole returned from her week in Florida with her mom and sister. I spoke to her only once when she was gone and missed her dearly. (Did I mention she's beautiful?) ALSO later that day two other long time friends got married. (Gratz Buckwheat and Vicki!) The wedding was beautiful, and the reception was hilarious. Good times all around. The next day, Saturday, being Labor Day weekend, we up and went camping at Malady Head park (2.5 hours from GFW). There were 12 of us, so we got a large group site as usual.

Well, that's my last week-and-a-bit. Quite a bit happened compared to my usual life, so maybe a little more interesting post than usual.

As a sort of fade out, here are some of the camping pics:



Left2Right: Deanna, Donna, myself, and Nicole.


Left2Right: Nicole, Greg, myself.


Left2Right: Nicole, Donna, Tom (my brother), and myself (tossing a horseshoe, our favorite camping game).