A somewhat smarter strongly typed resource generator

First, a word from our sponsor...

I work in a group named "DevLogic" here at FinRad. Our fearless leader was supposed to have posted an introduction to the group a while back, but he's a bit busy with actual work stuff, and I'm in a bit of a hurry to drop a couple of posts, so here's a really brief introduction to the DevLogic team...

FinLogic is FinRad's main commercial product. DevLogic is the internally built application framework on which it relies. The DevLogic team is responsible for maintaining and growing the DevLogic framework (hence the team name), but that's not all we do. Amongst other things, we're also responsible for developing tools for internal use by developers on all our product teams, and I'm hoping to post about two or three of those in the near future. The remainder of this post will be about one of those tools: an alternative strongly typed resource generator for Visual Studio.

Rabbit #1 leaves the hat...

If you have been using Visual Studio 2005 or 2008, chances are pretty good that you may have noticed the strongly typed resource generator tool that ships with these IDE versions. Unfortunately, until very recently (pretty much yesterday morning <g>), we had mostly been using Visual Studio 2003 at FinRad, which means that we didn't have access to the built-in tool. Actually, it turns out to be not all that unfortunate in this particular case, since our somewhat prolonged use of Visual Studio 2003 was sufficient motivation to prompt us to develop an analogous tool targeted at that IDE version, and we took the opportunity to (we think <g>) improve upon it a bit.

There were two main problems we saw with the Microsoft-provided resource code generator:

  1. Strong typing support only goes as far as the resource string identity. If there are placeholders in the resource string (e.g.: "The value provided for {0} exceeds the maximum value of {1}.", it's up to the resource consumer to format the string appropriately, which leaves quite a bit of room for error, particularly if the resource string is modified. Granted, unit tests can help find problems with broken formatting, but we would rather detect such issues as early as possible which, in this case, is pretty much at compile time.
  2. We prefer to allow exception messages to default to a language other than that indicated by the CurrentUICulture. Specifically, unless deliberately overridden by an application administrator, we want exception messages to be generated in English and formatted using the invariant culture regardless of the culture/language preferences of the end user.

The exception culture issue was quite a bit easier to address. We simply created two slightly different strongly typed resource generators: one for "end user" strings that defaults to using the CurrentUICulture for its resource lookups and CurrentCulture for its formatting, and another for exception message strings that defaults to using InvariantCulture for both its resource lookups and formatting. (Actually, the exception message generator that we use internally is a wee bit more complicated than this; it tries to default to an exception culture specified via the DevLogic framework before falling back on InvariantCulture. However, that's just a way of allowing us to centralize setting of an alternate culture given that there's no built-in .NET Framework concept of an alternate exception culture exposed by some handy property like Thread.ExceptionCulture or CultureInfo.ExceptionCulture.)

Formatting was a trickier problem to address or, rather, we made it more difficult by asking for quite a bit of fancy-pants functionality:

  1. Rather than using numbered placeholders that could be consumed directly by the String.Format method, we wanted to use named placeholders, with the placeholder names becoming argument names for formatting methods at code generation. For example, we wanted to be able to provide a resource string like "The value provided for {valueDescription} exceeds the maximum value of {maximumValue}." and have the tool generate a method with a signature like "FormatValueTooBigMessage(object valueDescription, object maximumValue)" for retrieving the already formatted string.1
  2. Despite using placeholder names rather than ordinal positions, we still wanted to support inclusion of formatting instructions inside the placeholders (e.g.: "Tickets for {showName} must be purchased on or before {lastPurchaseDate:yyyy-MM-dd}."). In addition, we wanted the formatting specifications from the resource string to appear in the IntelliSense help for the formatting method so that callers would be aware of any formatting that might be applied to the values they provide for the method arguments.
  3. A change in placeholder sequence within the resource string should not alter the sequence of arguments used in the method.
  4. If the placeholders included in a resource string change in any way (e.g.: renaming, addition, removal) other than sequence, we wanted any existing use of the retrieval property/method to break.

On the other hand, there is quite a bit that the Microsoft-provided resource code generator does for you that our tool does not, such as trying to generate legal property names from arbitrary resource labels or generating a property even for a non-string resource. Our tool assumes that the user developer is aware that the resource names are going to be used in member names and that he will consequently be reasonably careful when assigning resource names. As for non-string resources, the tool simply ignores them, so we place them in an alternate resource file that uses the Microsoft resource code generator tool.

If you're interested in giving the tool a whirl, an externally consumable version (i.e.: one that doesn't depend on our DevLogic-specific exception culture property mechanism) is available on CodePlex. A few things to know about the published release:

  1. This is pretty much an unsupported tool. You can report bugs or make change requests but, given that we're pretty busy working on our main product lines, chances aren't good that we'll make those changes unless they happen to coincide with our internal needs for the tool.
  2. If you would like to modify the tool for your own internal use, source code is available on CodePlex. You will need to generate your own strong naming key for signing the assembly if you want to compile a modified version since our key is not included in the source tree.
  3. Instructions for using the tool are available on CodePlex.

1We also played with the idea of allowing argument types to be specified within the placeholders, but opted to omit that for now since it impacted a bit too much on readability (and, hence, maintainability) of the original resource string.

Print | posted on Thursday, February 07, 2008 1:29 PM

Feedback

No comments posted yet.
Title  
Name
Email (never displayed)
Url
Comments   
Please add 1 and 8 and type the answer here: