comments suggest edit

Surprisingly, most of my good friends who read this blog don’t care much about software development or .NET. They’re not riveted by gripping stories of flexible configuration section handlers, or the heart palpitating episodes of my titanic battle with the StringDictionary’s handling of string casing. Nor do they spend their leisure moments contemplating new and exciting IBlogExtension plugins.

What, pray tell, do these people do for fun, you ask? It’s still a mystery to me.

Last night my friend Walter told me that his interest wanes when I post a long ode to code. He’s one of those guys who like to read the “Human Interest” stories in the paper (and my blog).

Many blogs (mine included) have post categories to group entries. I could suggest that he subscribe to every category except for the Software Dev & .NET, but as he uses Yahoo.com to subscribe, that would really clutter his main page. It’d be great if Yahoo provided the ability to subscribe to multiple categories of a single blog and present that as one blog. At the very least they could display the category for blog items.

However, if you don’t mind the clutter, here are links to the RSS feeds for each of my categories (thus far).

[Listening to: Star 69 - Fatboy Slim - Halfway Between The Gutter And The Stars (5:43)]

comments suggest edit

And I expect my arms to be tired (ba-dump pshhh).

We’re heading over there on July 28 to see my wife’s best friend (from back when they lived in Japan) and her husband.  She’s working on her residency at some hospital somewhere over there (I know so much). How’s the weather been up there? Being a transplanted Alaskan, I’m a big fan of the Northwest. I expect that the days will be nice and long. 

It’s been a long time since I’ve been up to Seattle. Any recommendations?

comments suggest edit

Finally I’ve gotten around to contributing an article to the Code Project community. Writing articles and whatnot has always been on my //TODO: list, but until now, I’ve only had articles published on my blog (not counting the RSS Bandit user documentation)

Surprise of surprises, the article I submitted is about a configuration section handler. Basically the same thing I posted here. Code Project is fine with that as long as I’m the copyright holder of the article.

Ok, so that’s two technical posts in a row, time to write something non-geek… Think! Think!

comments suggest edit

Ian Griffiths points out why he doesn’t like configuration section handlers much, and one of the primary reasons is how they require extra “cruft” in order to tell .NET about the handler. I have to agree for the most part. I’ve always wanted a #region tag for the App.config file just to hide that junk away, but that’s pretty much a cop out. Cyrus points out how the C# team was ambivalent about even having a region tag in the IDE.

One good point Ian and Craig (via email) brought up is that configuration sections are often misused. I should have stated this in my article, but I’ll state it here for the record. Perhaps I’ll even use an H2 tag and all caps. Here goes.

DO NOT STORE USER SETTINGS IN AN APPLICATION CONFIGURATION FILE!

That’s not what it’s there for. Remember, the application configuration file is stored in your application’s directory of the Program Files directory (by default). If you’re a proper windows logo programmer, you’ll know that the typical user should not have write access there. Otherwise you don’t deserve that shiny “Designed forWindows XP” icon.

I tend to write a lot of Windows Services. I try to build an installer for each one that provides a GUI for the user to enter in some configuration data which gets written to the config file upon installation. That’s pretty much the only time my config files get modified unless we need to adminstratively change something or other. Note the use of an administrator and not a user.

For more information about persisting user settings, check out:

comments suggest edit

Today I ran into an annoying nuance of the StringDictionary class (located in the System.Collections.Specialized namespace so as not to be confused with the other imposter string dictionaries). It’s not a bug, but I feel the API for it could have been slightly better on this minor point.

Right there in the documentation for the class it points out that:

The key is handled in a case-insensitive manner; it is translated to lower case before it is used with the string dictionary.

Thus it takes the key you give it, and changes it to a lower case value before storing it. I verified this with Reflector.

``

public virtual void Add(string key, string value)
{
      this.contents.Add(key.ToLower(CultureInfo.InvariantCulture), value);
}

Whoa there! Stop the presses! Call Michael Moore! Ok, ok. So in the grand scheme of things, it’s a minor issue. It’s not a huge deal. However, API usability (and language design) focuses on keeping the minor annoyances to a minimum. Otherwise they’ll add up and form a major disturbance and soon you’ll have an angry developer standing on his/her soap box whining and ranting about it on a blog.

The issue for me is that this wasn’t the behavior I expected. If an API is going to change data you give it, I wish it would indicate that somehow. Perhaps the method could be AddKeyAndValueButLowerCaseTheKey() ;). All joking aside, it isn’t necessary to lower-case the key before storing it in order to provide case-insensitive storage. Internally, StringDictionary uses a HashTable to store its keys and values. The dictionary could have made the HashTable use a CaseInsensitiveHashCodeProvider when storing keys. That way the key doesn’t have to change, but you get case insensitivity.

In any case, like I said, it’s normally not a big deal except for the fact that I am building a Setup and Deployment project within Visual Studio.NET for a Windows service. When building a project installer, the Installer (in the namespace System.Configuration.Install) class provides a property called Context of type InstallContext. This class gives you a property called Parameters which is a StringDictionary containing values you may have pulled from the user interface.

I’m trying to look up nodes within an XML file that correspond to the keys of the Parameters dictionary using XPath, hoping to update the node values with the values from the dictionary. However, XPath is case sensitive so I can’t match these things up. Unfortunately I can’t change the XML to be all lower case, and I can’t change the Installer class to not use a StringDictionary (or better yet, correct the dictionary’s behavior), so I’m stuck with resorting to a hack until something better comes along.

aspnet config comments suggest edit

UPDATE: In ASP.NET 2.0, there’s an even easier approach that supercedes this one. I wrote about it here.

A while back Craig Andera wrote an excellent article entitled The Last Configuration Section Handler I’ll Ever Need which outlines a really nice and flexible configuration section handler. It is certainly a big time saver and was the leading contender as the last one I would ever need as well. That is until I realized it lacked one minor feature I need: the ability to reload itself when the config file changes.

Before continuing, please do go and read his article for background. It’s pretty short and well written. No really, go read it while I listen to

American Dream (Joey Negro Club Mix) - Jakatta - Essential Mix - Mixed By Pete Tong (5:22)

Having read his article, it should be apparent why reloading the settings when the file changes is a challenge. Mainly because you most likely will have a reference to your simple settings object (such as the MyStuff class in the article) which has to somehow be notified that a change has occurred. As you can see from the sample below, classes used to hold settings (such as the MyStuff class) are deliberately kept very simple in order to facilitate writing many of them. There’s no facility to watch for changes to the config file.

public class MyStuff {
  public float Foo {
    get;
    set;
  }

  public string Bar {
    get;
    set;
   }
}

So after a bit of thought and a bit more beer, I came up with a solution that I believe still retains the simplicity of his approach, while adding the ability to have the settings dynamically get updated when the config file changes. My approach is also backwards compatible with existing setting objects created using his approach. Existing setting objects will not need any changes to work, though they won’t get the benefit of this new feature.

I’ve extended Craig’s solution with the addition of the XmlSectionSettingsBase abstract class. The purpose of this class is to act as the base class for your simple setting object. To add the ability to reload itself, just have your class inherit from XmlSectionSettingsBase and call the UpdateChanges() method before each property getter. As an example, I’ve modified the above settings object:

public class MyStuff : XmlSectionSettingsBase {
  private float foo;
  private string bar;

  public float Foo {
    get {
      UpdateChanges();
      return foo;
    }
    set { foo = value ; }
  }

  public string Bar {
    get {
      UpdateChanges();
      return bar;
    }
    set { bar = value;
  }
}

That’s it! That is the total amount of changes to the settings class needed so that it will now track changes. I’ve also updated the XmlSerializerSectionHandler class as well. It’s now pretty small:

public class XmlSerializerSectionHandler : IConfigurationSectionHandler {
  public object Create(object parent, object context, XmlNode section)  {
    return XmlSectionSettingsBase.LoadSettings(section);
  }
}

Which leads us to the XmlSectionSettingsBase class which is the workhorse of my scheme. You’ll notice that I’ve removed all the logic from the section handler for loading the settings object from the config file. The reason for this is that the instance of the settings object has to know how to load itself from the config file if its going to watch it for changes. Since I didn’t want to duplicate logic, I moved that code to this class. I’ll outline the class with some broad strokes and let you download the source code for the complete picture.

First, let’s start with the static LoadSettings method.

public static object LoadSettings(XmlNode section) {
  object settings = DeserializeSection(section);
  XmlSectionSettingsBase xmlSettings = settings as XmlSectionSettingsBase;
  if(xmlSettings != null) {
    xmlSettings._rootName = section.Name;
    ((XmlSectionSettingsBase)settings).WatchForConfigChanges();
  }
  return settings;
}

This method deserializes an instance of your settings object and checks to see if it inherits from XmlSectionSettingsBase. If not, it just returns, keeping this approach backwards compatible. Otherwise it calls WatchForConfigChanges which sets up a FileSystemWatcher to monitor for changes to the config file. Also notice that it stores the name of the config section node in a private member (_rootName) of the settings class. This becomes important later when we need to reload the settings.

void WatchForConfigChanges() {
  FileInfo configFile = new FileInfo(
    AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);
  try {
    _watcher = new FileSystemWatcher(configFile.DirectoryName);
    _watcher.Filter = configFile.Name;
    _watcher.NotifyFilter = NotifyFilters.LastWrite;
    _watcher.Changed += new FileSystemEventHandler(OnConfigChanged);
    _watcher.EnableRaisingEvents = true;
  }
  catch(Exception ex) {
    Log.Error("Configuration problem.", ex);
    throw new ConfigurationException("An error occurred while attempting to watch for file system changes.", ex);
  }
}

When a change occurs, the OnConfigChanged method is called. This method simply updates a boolean flag. This is the flag that the UpdateChanges method mentioned earlier checks before actually applying changes to the settings object.

void OnConfigChanged(object sender, FileSystemEventArgs e) {
  _isDataValid = false;
}

protected void UpdateChanges() {
  if(!_isDataValid)
    ReloadSettings();
}

Now we hit upon the ReloadSettings method. This method uses the name of the node containing the config section we stored earlier (_rootName) in order to load an XmlDocument containing the new settings from the config file.

void ReloadSettings() {
  XmlDocument doc = new XmlDocument();
  doc.Load(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);
  XmlNodeList nodes = doc.GetElementsByTagName(_rootName);
  if(nodes.Count > 0) {
    //Note: newSettings should not watch for config changes.
    XmlSectionSettingsBase newSettings =
      DeserializeSection(nodes[0]) as XmlSectionSettingsBase;
    newSettings._isDataValid = true;
    CopySettings(newSettings);
  }
  else
    throw new System.Configuration.ConfigurationException("Configuration section " + _rootName + " not found.");
}

The path to the config file is retrieved via a the AppDomain.CurrentDomain.SetupInformation.ConfigurationFile property. Once we have the section, we can call DeserializeSection to get an instance of our settings class with the new settings. This method is pretty is the same as the Create method in Craig’s version.

static object DeserializeSection(XmlNode section) {
  XPathNavigator navigator = section.CreateNavigator();
  string typename = (string)navigator.Evaluate("string(@type)");
  Type type = Type.GetType(typename);
  if(type == null)
    throw new ConfigurationException("The type ’" + typename + "’ is not a valid type. Double check the type parameter.");
  XmlSerializer serializer = new XmlSerializer(type);
  return serializer.Deserialize(new XmlNodeReader(section));
}

After loading this new settings instance, I overwrite the current instance’s property values with the values from the new settings instance via a call to CopySettings.

void CopySettings(object newSettings) {
  if(newSettings.GetType() != this.GetType())
    return;
  PropertyInfo[] properties = newSettings.GetType().GetProperties();
  foreach(PropertyInfo property in properties) {
    if(property.CanWrite && property.CanRead) {
      property.SetValue(this, property.GetValue(newSettings, null), null);
    }
  }
}

CopySettings uses reflection to iterate through all the public get properties of the new settings object and sets the corresponding property of the current instance if the current property can be written to.

Unfortunately this post is very old and I don’t have the source code for it anymore. In any case, there are better approaches you can use with ASP.NET 2.0 and above.

comments suggest edit

So I’m definitely going to see this movie this Friday. Regarding the reviews I posted on Saturday, Koba makes the following good point in my comments section:

I find parts of that Slate review to be disingenuous. It makes the point that if Moore would (among other things of a supposed pacifist leaning) have allowed Saddam to keep Kuwait. However, I’m going to go out on a limb here and hypothesize that if Michael Moore were in charge of the White House, I’m pretty sure the U.S. would not have joined Germany and France in giving weapons to Uncle Saddam to fight the Iranians (and oppress those living within Iraq’s borders). Apparently we are to believe that our aggression is better than (morally superior to) others’ aggression. \ \ Anyway, would Hitchens have us believe that our current motivations in Iraq are wholly noble? Please, our soldiers are sitting on the 1/9th of the world’s proven oil reserves. End of story.

Indeed!

comments suggest edit

We went camping in Sequoia National Park a couple of weekends ago, a weekend which happened to coincide with our first anniversary! Somehow I convinced my lovely wife that a weekend of camping in the woods among the bears is much preferable to a stay at a nice hotel resort. I mean who wants to be pampered and massaged?

Sequoia National Park is the home of some truly immense trees. I mean really really big trees. The kind of trees that give you a big cramp in the back of your neck if you try to stare at the top for too long, forcing you to walk around staring at the sky causing everyone around you to wonder what the hell you’re looking at. Redwoods may be taller, but no trees have the volume and bulk of the giant sequoias. These things almost seem to generate their own gravity.

Hello In There \ The author loses his head, once again.

This trip found us reuniting with a several members of our intrepid Buring Man 2002 crew. Upon arriving I nearly lost my head at the astounding dimensions of the trees. Pictured above is a little tunnel carved out of a fallen tree. That’s me sticking my head where the sun don’t shine. This fallen tree is one of many among the myriad of trails within the park. If a tree falls in the woods, will it muss up my wife’s pretty pink hat?

The Source of Evian \ The tree was no match for the power of the hat.

Sequoias are notable for the crazy tree people (though so is Green Peace). If you look carefully, you can see them hiding within the burnt trunk of a large tree. Counterintuitively, Sequoias thrive on fire (though not in the same way Cheech and Chong did). They need the occasional forest fire to to survive and thrive. Fires burn off the undergrowth, removing competition for good soil and water, basically keeping out the riffraff. When procreation becomes a priority, they drop off cones containing hundreds of seeds. The seeds remain safely huddled inside until a fire heats up the cone enough to cause the seeds to release. Wandering through the forest, you’ll notice a large number of trees that have grown a thick layer of bark around the scars from forest fires.

Dane Hiding In a Tree Trunk \ The last surviving member of Ponce De Leon’s crew.

Like a runaway pituitary gland, it’s seems that a giant sequoia never stops growing. They can live for a little over 3000 years and have a diameter (at the base) of up to 36.5 feet. If a tree survives fires and other hazards to reach a massive size, the typical cause of death is falling over from its own weight, much like the Lakers did in the finals recently. As can be seen below, its roots don’t run very deep. They dig in a mere three feet.

Roots \ So how do we drag this thing home?

We had this sequoia surrounded, but it wouldn’t be bullied by us and didn’t give up its wallet.

Hands across a sequoia \ Hands across America…a tree.

When camping in Sequoia, the rangers go to great pains to make sure you observe proper bear safety. They’ll go on and on about keeping all food and scented items safely stored away in bear containers. Don’t keep any food in your tent. Don’t feed the bears, no matter how cute they seem or how many GMail invites they offer. Apparently feeding a bear human is equivalent to giving them bear crack. They quickly acquire a taste for it and will go to great lengths to get more. They’ve been known to peel down the window of a car to get at the potential food inside. Sadly, this typically leads to the bears being put down. There were several bear sitings within the campgrounds, including the one sneaking up from behind me in the following photo.

Attacked By Ed Bear \ Unbeknownst to Gandalf, a feral Frodo approached.

A nearby campsite had a black bear crawl on top of their truck and scratch it up a bit, apparently looking for the keys to take it for a joy ride. We spotted the culprit the next morning relaxing in the sun.

Black Bear \ BooBoo was relieved to finally get rid of that annoying Yogi.

sql comments suggest edit

I found a nice tip for selecting random rows from within a SQL Server 2000 database. Well actually, pseudorandom. Since my undergraduate thesis was on the topic of pseudorandom number generation, I might as well be precise. For some reason, my non-geek friends find it awfully funny when I mention pseudorandom numbers.

I digress. In order to select 10 records from some table at random, try this:

SELECT TOP 10 * FROM someTable ORDER By NEWID()

Now for my homework, I should find out just how random this is. There’s a whole slew of statistical tests I can run to gauge the randomness of pseudorandom number generator such as the Chi-square Test, Serial Correlation Coefficient, and 2-D Random Walk Test to name a few.

IMPORTANT: Please note that this will NOT work in SQL 7 on NT4 because the NEWID() function there generates sequential results (Bad SQL! Bad!).

UPDATE: My friend Erik referred me to this article that has an overview of several methods for random sampling. Thanks e.

comments suggest edit

Michael MooreI found this scathing review on Slate of Michael Moore and his upcoming flick, Fahrenheit 9/11 I have yet to see the movie but plan to soon. It’s good to read a critical review to make sure I have a balanced view of the movie.

If Michael Moore had had his way, Slobodan Milosevic would still be the big man in a starved and tyrannical Serbia. Bosnia and Kosovo would have been cleansed and annexed. If Michael Moore had been listened to, Afghanistan would still be under Taliban rule, and Kuwait would have remained part of Iraq. And Iraq itself would still be the personal property of a psychopathic crime family, bargaining covertly with the slave state of North Korea for WMD.

I don’t doubt that Michael Moore is biased and self-serving. His movie is designed to provoke a strong reaction, and whether the facts are misinterpreted or self-contradicting, that’s not important to his goals. I figure I will have to take his message with a grain of salt. Many will see his movie once, while they watch Fox news every day. The truth probably lies somewhere in the middle.

As a counterpoint to the scathing review, I offer up another review that points out the great lengths the Moore team went to fact check all their assertions. The review does point out that Moore does insert his prejudices in places, but that his central assertion is well-founded.

Moore is on firm ground in arguing that the Bushes, like many prominent Texas families with oil interests, have profited handsomely from their relationships with prominent Saudis, including members of the royal family and of the large and fabulously wealthy bin Laden clan, which has insisted it long ago disowned Osama.

comments suggest edit

Margaret Cho RevolutionWe recently saw Margaret Cho try out some new material in Claremont. I think she’s absolutely hilarious and poignant. Some say she relies way too much on her Korean mother, but having a Korean mother myself, I think she’s spot on with the impression.

I’m looking forward to seeing her next big movie Revolution. Here’s a nice review from Slate.com.

comments suggest edit

RSS Bandit Logo Plug-ins are a powerful way for users to dynamically enhance the functionality of an installed application. Is there a high priority feature you want that is low priority for the developers? Perhaps you can write a plug-in.

Many RSS aggregators support the ability to add plug-ins through the IBlogExtension interface. Started by Simon Fell, the IBlogExtension is intended to provide news aggregators an extensibility point so that they can be hooked into 3rd party blogging tools such as w.Bloggar.

RSS Bandit is one such aggregator. I recently added documentation which includes a walkthrough for building a very simple plug-in. Please let me know if it is helpful or if you find any errors by commenting here or in the RSS Bandit IBlogExtension forum.

I’m working on a more advanced plug-in complete with configuration settings and a GUI that I will present later.

comments suggest edit

Snippet
CompilerRegarding Syntax Highlighting, Daniel Turini pointed out that SnippetCompiler has the ability to export code to the clipboard (and to a file) as HTML.

Snippet Compiler has a lot of nice features and is a welcome addition to my toolbox, but purely for syntax highlighting, it has a few disadvantages compared to the manoli.net website I mentioned previously. First of all, although you can view snippets with line numbers, the line numbers aren’t exported to HTML like Manoli does. Secondly, Manoli handles XML/HTML along with C# and VB, while SnippetCompiler seems to do well only with C# and VB.NET. Lastly, Manoli uses CSS for styling and you can have it embed the CSS definitions in the generated HTML, or reference the provided stylesheet. This is a really nice feature.

One thing I do like about the SnippetCompiler is how the summary tags in the comments are gray while the actual comment is green. That’s a nice touch.

``

///&ltsummary>
///Manages cool things
///</summary>
public class ThisIsSoCool
{
    /// 
    /// This is seriously neat. 
    /// 
    public void YouShouldTryThis()
    {}
}

comments suggest edit

I’ve probably read a hundred or so posts of people looking for a way to syntax highlight source code listings in HTML. Maybe I’m the last to discover this site, but http://www.manoli.net/csharpformat/ is the answer for me so far. Just cut and paste some C#, VB, html/xml/aspx code int the text box and click “format my code” and voila! You get some clean HTML displaying nicely formatted code.

The tool allows you to optionally format the code with alternating line colors and line numbers if you so desire.

public class ThisIsSoCool
{
  ///      /// This is seriously neat.      ///      
  public void YouShouldTryThis()
  {}
}

Let’s try it with line numbers.

``

   1:  public class ThisIsAlsoCool

   2:  {

   3:    /// 

   4:    /// Look at me ma! I’m using line numbers

   5:    /// 

   6:    public void YouShouldTryThis()

   7:    {}

   8:  }