# Thursday, January 15, 2009
Yet another day of the CAB... I was using a customized Window-Workspace with my own derived SmartPartInfo. This SPI included a key-string which I usually filled with a primary key of an entity for which the window was shown (simple edit dialog). I used the key to check if the window is already opened so it was impossible to open/edit the same Entity twice. So far so good, but finally my key was always null in one of my dialogs. The only thing that was different to another (working) dialog was that I tried to change the title of the window after it was shown and I did this by giving it just a simple SmartPartInfo. So it was some older code but I was still wondering why it did not crash anyway - I thought wether the ApplySmartPartInfo-Method would have recognized that its "only" a SmartPartInfo or it wouldn't and a cast to my derived type would have failed.
Well, as often .NET Reflector solved the mystery.. turned out that CAB looks at both types - the Template-Argument for the SmartPartInfo-Type and the type of the given SPI-instance and uses Type.IsAssignableFrom to determine if the given instance is -or at least inherits from- the template-Type. If not -and thats the catch- it uses Workspace.ConvertFrom which will create a fresh new Template-Type SmartPartInfo (with all its default values set of course) and copies only the two things that it knows from ISmartPartInfo to the new instance: Title and Description. And so my key was rewritten and the whole stuff didn't work but also did not crash or anything other wrong...

posted on Thursday, January 15, 2009 2:21:43 PM (W. Europe Standard Time, UTC+01:00)  #    Comments [0]
# Monday, December 01, 2008
Few days ago I was trying to put some Guids into the ItemCollection of a fresh, new WorkItem - I used that pattern earlier and never noticed anything strange going on. But this time was a totally different... What I did was something like this:
Guid a = Guid.Empty;
Guid b = Guid.Empty;

WorkItem.Items.Add(a, "A");
WorkItem.Items.Add(b, "B");
so since this point of development I didn't had the needed Values so I filled empty guids to test other stuff before implementing this. So at another point I tried to get the values out of the collection by its keys "A" and "B" (well I had real names for it but lets keep it simple)
Guid a = (Guid)WorkItem.Items["A"];
Guid b = (Guid)WorkItem.Items["B"];
unfortunally this threw an exception sometimes because null was returned... Yes - sometimes - not always... Nice... As I took a closer look it turned out that only the second line might crash and that the chance that this happens was growing with the elapsed time since I put the Guids in... so at this point it seemed a bit like radioactive decay... ok you'll guess that it was not only time - so I could speed up the decay by doing some operations in my window... I suspected it had something to do with the garbage collection since it is done asynchronously and may occur more often the more operations allocate memory. Besides there is no way to put any null in the WorkItem.Items-Collection which means that no other side effect should be abled to have Item B modified.
I played a bit around and found out, that always the last inserted item might disappear while the other one was stable. I also figured out that different values made both items stable so I asked myself if there might be any selfcleaning process in the CAB that would remove duplicates sometimes but what would that make sense for since the items where added with an explicit ID ("A" & "B").

Ok the solve of the mystery was quite a bit of both... so a little session with the .NET Reflector later I think I found what explained this. It turned out that even when an explicit ID was given the collection was searched for an Equal value. If it found one it did not add the Item to the list instead it used a method called BuildRepeatedItem and this -some levels deeper- (through the ReadWriteLocator...) led into not adding it to any list but into a Dictionary<TKey, WeakReference> and like its written on a Microsoft page:

"WeakReference Class - Represents a weak reference, which references an object while still allowing that object to be reclaimed by garbage collection."

nice... so whats the error here anyway? I don't currently see why a WeakReference should be applied to something that comes from the "API-User" and could be anything. On the other hand it does also not make much sense to compare the values if an ID is given. Ok maybe it was never intended to add simple value types into the workItem.Items-Collection but I think the problem would never occur if the Contains-Check in the Collection would have been done in a ReferenceEqual-comparison way instead of an Equality-comparison which leads to different results with value and reference types.

posted on Monday, December 01, 2008 5:03:02 PM (W. Europe Standard Time, UTC+01:00)  #    Comments [0]
-