C# .NET - Using an Enum to Get a Resource
There are a variety of reasons one might want to get a resource associated with an enum
element. For example, it might be necessary to find an error message to display to a user or return in a web service call. Or, perhaps you need to find an icon associated with a status, etc. This article shows how to find a string from a resource file based on an enum
element.
Now, assume there is an enum
named MyEnum
defined as shown below:
public enum MyEnum
{
Alpha,
Bravo,
Charlie
}
And, assume that there needs to be a description associated with each of the enum
elements. Each of the element names ("Alpha", "Bravo", "Charlie") can be added into the string table of the project's resource file (.resx). If desired, since there is no limit to the number of resource files that can be included as part of a single project, one could even create a separate resource file just for these values.
Key | Value |
---|---|
Alpha | Alpha is the first value. |
Bravo | The second value is Bravo. |
Charlie | The third value, Charlie, is here too. |
The next step is to create a simple mechanism to access the value from the string resource from an enum
element. An extension method comes to mind, as it would be really handy to be able to something like the following:
// Get the description directly from an enum literal
string description = MyEnum.Alpha.XGetDescription();
// Get the description directly from an enum variable
var myEnumVariable = MyEnum.Bravo;
string myEnumDescription = myEnumVariable.XGetDescription();
There is no technical reason that an extension method must start with 'X', but that is my personal preference; I find it conceptually useful to distinguish extension methods (which can be called successfully on null objects) from instance methods (which throw exceptions when called on null objects).
Creation of the extension method is simple. Basically, there must be a static class with the static method XGetDescription()
, and that method must take type this MyEnum
as the first parameter. See the example below.
public static class MyEnumExtensions
{
// Create an instance of the ResourceManager class, and store it as a static variable
// so the same instance can be used multiple times. Note that the
// [typeof(MyProjectResources)] assumes that the strings are stored in a resource file
// named "MyProjectResources.resx", so that will need to be changed to the class type
// that is created for your resource. Static fields do not have to start with "s_",
// but that is what I like to do.
private static ResourceManager s_ResourceManager =
new ResourceManager(typeof(MyProjectResources));
// This is an extension method for the type [MyEnum] because it is a static method on
// a static class, and the first parameter is of type [this MyEnum].
public static string XGetDescription(
this MyEnum value)
{
// Define a string format that will be used if the matching value is not found in
// the resource file. Hopefully that does not happen because programmers will
// remember to keep the resource updated as elements are changed or added to the
// enum, but better to be safe than sorry.
const string RESOURCE_NOT_FOUND_FORMAT =
"Unable to find string resource for resource key '{0}'.";
// Use the ResourceManager instance to lookup the key that is the name of the enum
// element ("Alpha", "Bravo", "Charlie"). If the resource is found then return the
// string from the resource file. But, if the resource is not found the
// [GetString()] method will return null, which means the ?? operator will execute
// the [String.Format()] to build a default string.
return s_ResourceManager.GetString(value.ToString())
?? String.Format(RESOURCE_NOT_FOUND_FORMAT ,value);
}
}
If you want to be more flexible, you can prefix the resource keys with the name of the enum
type (MyEnum), and suffix the resource keys with the "Description" (since the method XGetDescription()
method is being used). That will allow the same enum element name to be used in multiple enums, and allow different types of resources (for example icons) to also be associated with the same enum element name.
Key | Value |
---|---|
MyEnum_Alpha_Description | Alpha is the first value. |
MyEnum_Bravo_Description | The second value is Bravo. |
MyEnum_Charlie_Description | The third value, Charlie, is here too. |
To support this, a few tweaks are necessary. Basically, the XGetDescription()
extension method has to be modified to create the key it is looking for instead of assume the key is simple value.ToString()
.
public static string XGetDescription(
this MyEnum value)
{
const string RESOURCE_KEY_FORMAT = "{0}_{1}_{2}";
const string RESOURCE_NOT_FOUND_FORMAT =
"Unable to find string resource for resource key '{0}'.";
// Create a resource key that will look something like "MyEnum_Alpha_Description".
// There is no need to call [.Tostring()] on the [value] parameter, as the
// [String.Format()] will do that automatically.
var resourceKey = String.Format(
RESOURCE_KEY_FORMAT,
typeof(MyEnum).Name,
value,
"Description");
// Tweak the [GetString()] to use the computed resource key instead of just
// [value.ToString()].
return s_ResourceManager.GetString(resourceKey)
?? String.Format(RESOURCE_NOT_FOUND_FORMAT ,value);
}
Programmer, Engineer