Click here to Skip to main content
15,887,596 members
Articles / Programming Languages / C# 3.5
Tip/Trick

Verify Resources Used by DisplayAttribute

Rate me:
Please Sign up or sign in to vote.
5.00/5 (1 vote)
17 Feb 2015CPOL1 min read 11.3K  
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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Netherlands Netherlands
Developer at AlertA contractbeheer.

Comments and Discussions

 
-- There are no messages in this forum --