Tuesday, November 18, 2008

Don't change semantics of well-known types!

I was writing a little quick and dirty PowerShell script to compare items in Visual Studio 2008 and Visual Studio 2010 project files side-by-side to ensure they are kept in sync.

Now I will admit that I am a total PowerShell newbie but I was not prepared to deal with this oddity:

$xml = New-Object System.Xml.XmlDocument
$xml.Load($path)
$nsmgr = New-Object System.Xml.XmlNamespaceManager $xml.psbase.NameTable

(...crash... cannot resolve the constructor for XmlNamespaceManager...)

See that little psbase?  Well, because without it, PowerShell will apply some kind of built-in adapter semantics.  Instead of giving back the NameTable, it will actually try to look for an element or attribute called "NameTable" and return that.  Of course, since it doesn't find one, it returns Null instead!

Now I'm sure PowerShell provides some cool Xml slinging features I don't know about right now.  However it's also a .Net language bound to the .Net framework.  It just diverged pretty dramatically from my mental model of some pretty fundamental .Net framework types.  It takes time to figure that out and recover...

This isn't like adding a fairly innocuous Ruby-ish to_s() method to types as an alias for ToString().  This is instead rather intrusive behavior that changes what member selection means for all XmlDocument objects.  I think it would be better if PowerShell introduced its own Xml type instead.  Then it could play with the semantics all it wanted while still preserving the expected behavior of the member selection operator.

Are there any other landmines I should beware of?

2 comments:

tomasr said...

Sorry dude, but that's one of the coolest features in powershell, and makes it a lot easier to deal with XML most of the time.

Besides, seriously, remember that PowerShell is aimed initially at sysadmins, and you don't expect them to know the details of the original .NET APIs right from the start (and the DOM is a really shitty API anyway), so providing simplifications like this over it is very helpful in that situation.

As for the nametable, the original node properties are all available in their method forms; i.e. call doc.get_NameTable()

Anonymous said...

Great, now how about adding some documentation? The docs are almost non-existent.