Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Verify Resources Used by DisplayAttribute

0.00/5 (No votes)
17 Feb 2015 1  
Code for verifying the resources used by DisplayAttribute in order to catch any missing resource strings

Introduction

A project that I am working on makes heavy use of the DisplayAttribute from the System.ComponentModel.DataAnnotations namespace. Because the application is localized in various languages, I make use of resource files.

The problem is that in case one makes a type in the name of one of these resource strings, the application will only throw an error during runtime. I wrote some code to verify all the DisplayAttributes I used in my project in a unit test, allowing me to check the validity without any manual labour.

Background

The DisplayAttribute is used as follows in a localized application:

C#
[Display(Name = "PropertyName", ResourceType = typeof(YourProject.Resources.Strings))]

public string Name { get; set; }

In the example case, a resource string named "PropertyName" should exist in the YourProject.Resources.Strings resource file. If it does not and your code attempts to make use of the DisplayAttribute, you'll see the following exception:

InvalidOperationException

Cannot retrieve property 'Name' because localization failed.  
Type 'YourProject.Resources.ContractStrings' is not public or does not contain 
a public static string property with the name 'PropertyName'.

The most elegant way would be to come up with some statically typed solution, which can check the presence of the resources at run time. This would eliminate the problem all together. I have however not yet seen such a solution.

In order to catch any misspelled or missing resource names before deployment and without manual testing, I created a unit test, which uses all the DisplayAttributes I used in my code.

Using the Code

Wrap the code below in a unit test. Make sure to update the assembly selection query in the first line.

Note that you need to make sure that the relevant assemblies are loaded in the application domain when running this test.

C#
// Only treat assemblies which are relevant. 
// I look for assemblies containing some kind of keyword in their name
// which ensures that no third party assemblies are considered.
var assemblies = AppDomain.CurrentDomain.GetAssemblies().Where
        (a => a.FullName.ToLower().Contains("yourKeyword"));
foreach (var assembly in assemblies)
{

    // Lookup all the members in this assembly which are decorated with a display attribute.
    var members = assembly.GetTypes()
        .SelectMany(type => type.GetMembers().Where
                (m => Attribute.IsDefined(m, typeof(DisplayAttribute))));
    foreach (var member in members)
    {
        foreach (var attribute in member.GetCustomAttributes
                (typeof(DisplayAttribute), true).Cast<DisplayAttribute>())
        {

            // Invoke the name and description resolving functions on the attribute instance.
            // Any missing resource strings should cause exceptions to be thrown here.
            attribute.GetName();
            attribute.GetDescription();
            attribute.GetShortName();
        }
    }
}

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here