Localizing DisplayNameAttribute

When trying to put a localized string from a resource file (.resx) into the DisplayName Attribute you will get a the following build error:

An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type

An easy way to solve this is to create your own custom DisplayName Attribute. To do that we will create a new class DisplayNameLocalizedAttribute and derive it from the original DisplayNameAttribute and then override the base DisplayName property to return the resource object we want.


public class DisplayNameLocalizedAttribute : DisplayNameAttribute
{
    private readonly string m_ResourceName;
    private readonly string m_ClassName;
    public DisplayNameLocalizedAttribute(string className, string resourceName)
     {
         m_ResourceName = resourceName;
         m_ClassName = className;
     }

     public override string DisplayName
     {
         get
         {
             // get and return the resource object
             return HttpContext.GetGlobalResourceObject(
                    m_ClassName,
                    m_ResourceName,
                    Thread.CurrentThread.CurrentCulture).ToString();
         }
     }
}

Use:


    [DisplayNameLocalized("MyResource", "MyString")]
    public string MyProperty { get; set; }

As you can see, we are now able to pass in a resource name (className) and a resource key (resourceName) and will get the correct string returned. The same procedure should work with similar Attributes such as the DescriptionAttribute.

Update 1: Another way would be by using reflection.

public class DisplayNameLocalizedAttribute : DisplayNameAttribute
{
    private string _displayName;

    public DisplayNameLocalizedAttribute(string resourceKey, Type resourceType)
    {
        PropertyInfo propInfo = resourceType.GetProperty(resourceKey,
                System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
        _displayName = (string)propInfo.GetValue(propInfo.DeclaringType, null);
    }

    public override string DisplayName
    {
        get
        {
            return _displayName;
        }
    }
}

Use:

[DisplayNameLocalized("MyString", typeof(MyResource))]
public string MyProperty { get; set; }

Update 2: In .NET 4.0 this procedure seems to be obsolete as you can just use the new [Display]-Attribute and specify the “ResourceType” and “Name” Properties:

[Display(ResourceType = typeof(MyResource), Name = "MyString")]
public string MyProperty { get; set; }
Advertisements
%d bloggers like this: