Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I output a property with the DisplayFormat DataFormatString applied in a console app (ideally querying the object by string)?

Here's a simplified look at a class I have:

public class SalesMixRow
{
    [DisplayFormat(DataFormatString = "{0:c0}")]
    public decimal? DelSales { get; set; }
}

In a web app razor view, I can get that value as formatted with:

@Html.DisplayFor(model => model.DelSales)

I have a console app that needs to output this value as well. How can I output it in a console app without repeating the DataFormatString anywhere?

Update: I like the idea of using reflection, because that solves a question that I was going to ask separately! Here is a complete working sample, where I get a property by string path and output with DisplayFormat if available:

void Main()
{
    var model = new SmrDistrictModel
    {
        Title = "DFW",
        SalesMixRow = new SalesMixRow
        {
            DelSales = 500m
        }
    };

    Console.WriteLine(FollowPropertyPath(model, "Title"));
    Console.WriteLine(FollowPropertyPath(model, "SalesMixRow.DelSales"));
}

public static object FollowPropertyPath(object value, string path)
{
    Type currentType = value.GetType();
    DisplayFormatAttribute currentDisplayFormatAttribute;
    string currentDataFormatString = "{0}";

    foreach (string propertyName in path.Split('.'))
    {
        PropertyInfo property = currentType.GetProperty(propertyName);
        currentDisplayFormatAttribute = (DisplayFormatAttribute)property.GetCustomAttributes(typeof(DisplayFormatAttribute), true).FirstOrDefault();
        if (currentDisplayFormatAttribute != null)
        {
            currentDataFormatString = currentDisplayFormatAttribute.DataFormatString;
        }
        value = property.GetValue(value, null);
        currentType = property.PropertyType;
    }
    return string.Format(currentDataFormatString, value);
}

public class SmrDistrictModel
{
    public string Title { get; set; }
    public SalesMixRow SalesMixRow { get; set; }
}

public class SalesMixRow
{
    [DisplayFormat(DataFormatString = "{0:c0}")]
    public decimal? DelSales { get; set; }
}
like image 809
Chris Avatar asked Nov 18 '12 19:11

Chris


1 Answers

You could retrieve the attribute from the class using reflection. Then get the format string from the attribute, and apply it using string.Format.

SalesMixRow instance = new SalesMixRow { DelSales=1.23 };

PropertyInfo prop = typeof(SalesMixRow).GetProperty("DelSales");
var att = (DisplayFormatAttribute)prop.GetCustomAttributes(typeof(DisplayFormatAttribute), true).FirstOrDefault();
if (att != null)
{
    Console.WriteLine(att.DataFormatString, instance.DelSales);
}

(Note that you'll need to add the assembly System.ComponentModel.DataAnnotations.dll, which contains the DisplayFormat attribute.)

like image 131
McGarnagle Avatar answered Oct 18 '22 03:10

McGarnagle