The ConfigurationManager class introduced in .NET 2.0 makes it easy to read application settings from an XML file. I especially like the ability to derive a class from ConfigurationSection to hold custom settings for your application. This MSDN tutorial on creating custom configuration sections can help you get started.
I used this to make the configuration files for several of our Infovark add-ins, but ran into a snag with our main API library. In order to interoperate with COM, we had to put out Infovark.Api.dll in the GAC.
This presents a big problem for using *.config files. If your assembly is in the GAC, your configuration file must live in the GAC as well. (By default, configuration files are sidecar files located in the same directory as your *.exe file.) Since the GAC lives in a special place on a Windows machine, it’s difficult to read and write from that location without special permissions. And you can forget about browsing to it using Windows Explorer. This makes it tough for folks to change configuration options, which defeats the whole point of XML-based configuration files.
It’d be nice if we could load the configuration file from an specific spot on the computer. But while the Configuration object has both
SaveAs() methods, there’s no corresponding
Load() method. Huh? According to MSDN, the “right” way to point your application at a different configuration file is to create a whole new app domain with the appropriate settings. Um… sure.
How about we just hack up a workaround instead?
You can fool the configuration object into loading settings from whatever .config file you want, if you don’t mind a hack or two. The Configuration object exposes an
OpenExeConfiguration() method that takes a string. Despite its name, you don’t have to pass it an .exe file. Any file path will do, as long as the path exists.
Since my .dll was in the GAC, I didn’t have a target for the
OpenExeConfiguration() to use. I could have pointed it at another .dll — or at a .txt file for that matter — but that wouldn’t be very intuitive. Instead, I created a temporary file without an extension in the location I wanted to save the configuration file. Then I can open a Configuration object using the dummy target. Saving the Configuration object will cause it to write a file named “[configurationTarget].config” to the path I specified. You can see the code I used below.
Once I’ve opened the Configuration object, I don’t need the dummy file any more. I delete it to avoid have weird extension-less files hanging around.
It’s not pretty, but it gets the job done.
We just finished our trial period for ReSharper from JetBrains. We’re buying licenses right now. It’s become indispensable to us. It’s that good.
Gordon had used ReSharper in its 2.0 days. I’d heard many positive things about ReSharper, but hadn’t tried it myself. The recently released 4.0 version offers support for C# 3.5, including the
var keyword, object and collection initializers, and lambda expressions. Check out the in-depth review by Simon Hart if you want more details. Or just try it yourself.
Enumerations are incredibly useful in Microsoft .NET, but they can be odd to work with at times. While researching something to do with the new System.Addin namespace in C# 3.5, I was reminded of some enum craziness I’d forgotten.
Enumerations are implemented as collection of integer constants. You can cast any integer to an enum type, regardless of whether it’s been defined in the collection. That makes the code below legal, despite the fact that no item in our enum has a value of 55.
You can’t rely on the compiler to enforce legal enum values. This means if you’re using enums in
case statements, you ought to include a
default statement to catch those cases where an unexpected value gets passed. It’s always a good defensive coding measure, but I’d mistakenly assumed I could skip it in the case of enums. Not anymore.
[Edit: See this old post from Greg Vaughn for some other examples of Enum wackiness. Weird.]
I needed a regular expression to correctly parse ISO 8601 format dates and times. The standard includes many alternative representations, but I was particularly concerned about the subset of ISO 8601 formats allowed in XML.
Edit 26 May 2009: If you want full ISO compliance, check out the expression Cameron Brooks lists in his comment below.
Paul Ward had posted a date parsing expression on the RegExLib site. I extended it a bit to handle times and time zones. I’m pretty sure they work, though it can be hard to tell sometimes. (See Jeff Atwood’s Now You Have Two Problems.)
ISO date and time
ISO date, time, and offset (the works)
If you find it useful — or find a bug — let me know.
Edit 21 Jan 2008: Stan James sent us some enhancements to the validation routines. Here’s what he had to say:
I needed a RegExp that could detect ISO dates with varying precision. (e.g. “1945”, “1945-12”, “1945-12-01”, “1945-12-01T12:15” etc..)
For future readers, here’s what I came up with:
Date and Time