2

Currently I'm working on a project where we have a query builder - the user selects what data he wants, what is shown on the final report and a few filters. We are also using Entity Framework (Code First) and we need the name of every string property of some classes. E.g.:

  1. Model Class

    public class User {
         public int Id { get; set; }
         public string FullName { get; set; }
         public string FullAddress { get; set; }
    }
    

As of now, I'm getting every property name like so:

  1. Property Filter

    var propertyList = type.GetProperties()
            .Where(prop => prop.PropertyType == typeof(string))
            .Select(prop => prop.Name).ToList();
    

And it works nicely for any change we make to the database, but it's not easy to read for the user (especially if you consider we need to keep all the code in English, even tough we'll publish it for people who mostly only speak Portuguese).

What I need is to display "FullName" as "Nome Completo", "FullAddress" as "Endereço Completo", etc, and still be able to get the original name somehow.

One solution I thought of was making a static dictionary and update it as needed; it's easy to process with jQuery (two way dictionary made with a simple object) but it'll be a pain to maintain since the database can get really big.

Are there any better options than static dictionaries?

2 Answers2

1

You can apply a DisplayAttribute to the properties and link it to a resource file with the friendly names in English and/or Portuguese. This is the same way that MVC works. When you need to get the friendly name you just need to call the GetName() method on the attribute to get the appropriate name in the current Thread Culture.

Model Class

// add reference to System.ComponentModel.DataAnnotations to your project
public class User
{
    public int UserId { get; set; }

    // pass the "key" of the resource entry and the name of the resource file
    [Display(Name = "FullName", ResourceType = typeof(UserResources))]
    public string FullName { get; set; }

    [Display(Name = "FullAddress", ResourceType = typeof(UserResources))]
    public string FullAddress { get; set; }

    public string OtherProp { get; set; }
}

UserResources.resx

Default English version (you could just put the Portuguese in here if the website itself isn't truly "multi-lingual")

FullName       Full Name
FullAddress    Full Address

UserResources.pt-pt.resx

Portuguese translations

FullName       Nome Completo
FullAddress    Endereço Completo

Helper Method

This will retrieve the translated display name if a [DisplayAttribute] is present. If not, just the name of the property.

private static string GetPropertyName(PropertyInfo prop)
{
    var displayAttribute = prop.GetCustomAttribute<DisplayAttribute>();
    if (displayAttribute != null)
    {
        // GetName() fetches from the resource file of the current Thread Culture
        return displayAttribute.GetName();
    }
    else
    {
        return prop.Name;
    }
}

Sample Usage to get list of property names

public static void Main(string[] args)
{
    // Uncomment to get the names in Portuguese
    //Thread.CurrentThread.CurrentCulture = Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("pt-PT");

    Type type = typeof(User);
    var propertyList = type.GetProperties()
        .Where(prop => prop.PropertyType == typeof(string))
        .Select(prop => GetPropertyName(prop)).ToList();

    foreach (string propertyName in propertyList)
    {
        Console.WriteLine(propertyName);
    }
}

The only other thing to note is that the resource file class is generated as an internal class by default and you will probably need to make it public. You can do this by setting the Custom Tool in the Properties window in Visual Studio to PublicResXFileCodeGenerator. Otherwise you may get an error saying "no public property FirstName found in resource file".

Rhumborl
  • 16,349
  • 4
  • 39
  • 45
0

If you right click on a table, or a column, in SQL Server Management Studio, and select properties, you will see that there is an option for Extended Properties. You could add an extended property called Friendly Name for each column, then have a separate query to load your dictionary at the applications start.

Here is a query that will help you pull Extended Properties for columns in your database.

SELECT major_id, minor_id, t.name AS [Table Name], c.name AS [Column Name], value AS [Extended Property], ep.name as [Property Name]
FROM sys.extended_properties AS ep
INNER JOIN sys.tables AS t ON ep.major_id = t.object_id 
INNER JOIN sys.columns AS c ON ep.major_id = c.object_id AND ep.minor_id = c.column_id
WHERE class = 1;

Example brazenly stolen from the following url (I make no pretense of having this stuff memorized): http://technet.microsoft.com/en-us/library/ms186989(v=SQL.105).aspx

Peter Lange
  • 2,786
  • 2
  • 26
  • 40