Как реализовать свой DisplayFormatAttribute атрибут?

170
29 декабря 2018, 16:50

Есть следующий класс

public class Request
{
    public int Downtime {get;set;}
}

свойство Downtime содержит кол-во минут. Подскажите как реализовать свой атрибут по аналогии с DisplayFormat, т.е. что бы для свойства можно было указать какие то свойства, а внутри будет скрыта некоторая логика, например: $"{downtime/60}:{downtime%60}").

Мне это необходимо для создания универсального метода выгрузки результата запроса в excel. Заготовка метода выглядит так:

public void PrintRows<T>(ExcelWorksheet sheet, IEnumerable<T> rows, bool printTitle = false) where T: class
{
    var columns = (from property in typeof(T).GetProperties()
                   let attribute = property.GetCustomAttributes(typeof(DisplayAttribute), true).SingleOrDefault() as DisplayAttribute
                   let format = property.GetCustomAttributes(typeof(DisplayFormatAttribute), true).SingleOrDefault() as DisplayFormatAttribute
                   where attribute != null
                   orderby attribute.Order
                   select new
                   {
                       Property = property,
                       Order = attribute.Order,
                       Name = attribute.Name,
                       Format = format?.DataFormatString ?? string.Empty
                   });
    var rowNumber = 1;
    if (printTitle)
    {
        foreach (var column in columns)
        {
            sheet.Cells[rowNumber, column.Order].Value = column.Name;
        }
        rowNumber++;
    }
    foreach (var row in rows)
    {
        foreach (var column in columns)
        {
            var value = column.Property.GetValue(row, null);
            sheet.Cells[rowNumber, column.Order].Value = value;
            if (!string.IsNullOrEmpty(column.Format))
            {
                sheet.Cells[rowNumber, column.Order].Style.Numberformat.Format = column.Format;
            }
        }
        rowNumber++;
    }
}
Answer 1

Возможно такой пример подойдет вам или натолкнет на мысль в нужном направлении.

Заведем базовый атрибут для кастомного форматирования:

[AttributeUsage(AttributeTargets.Property)] // Можно применять только к свойствам
public abstract class CustomFormatAttribute : Attribute
{
    public abstract string Format(object value);
}

Пара реализаций для примера:

public class TimeFormatAttribute : CustomFormatAttribute
{
    public override string Format(object value)
    {
        var time = (int)value;
        return $"{time / 60 :00}:{time % 60 :00}";
    }
}
public class MoneyFormatAttribute : CustomFormatAttribute
{
    public override string Format(object value)
    {
        var money = (decimal)value;
        return $"{value} руб.";
    }
}

Класс элемента:

class Item
{
    public int Number { get; set; }
    [TimeFormat]
    public int Time { get; set; }
    [MoneyFormat]
    public decimal Money { get; set; }
}

Пусть теперь у нас имеется некая коллекция таких элементов:

var items = new[]
{
    new Item { Number = 10, Time = 300, Money = 299.95M },
    new Item { Number = 20, Time = 250, Money = 287.95M },
    new Item { Number = 30, Time = 200, Money = 275.95M },
    new Item { Number = 40, Time = 150, Money = 263.95M },
    new Item { Number = 50, Time = 100, Money = 251.95M }
};

Применяем кастомное форматирование:

var props = typeof(Item).GetProperties();
foreach (var item in items)
{
    foreach (var prop in props)
    {
        var value = prop.GetValue(item);
        var attribute = prop.GetCustomAttribute<CustomFormatAttribute>();
        Console.WriteLine(attribute?.Format(value) ?? value);
    }
    Console.WriteLine();
}
READ ALSO
Почему не выделяется первый вариант в Intellisense?

Почему не выделяется первый вариант в Intellisense?

Пишу например название класса, мне Intellisense подсказывает правильный класс, но он не выделяется в подсказке, а соотвественно я не могу просто...

155
Вывести родительские рубрики записи (WordPress)

Вывести родительские рубрики записи (WordPress)

Как можно в записи вывести родительские рубрики?

176
foreach в многомерном массиве

foreach в многомерном массиве

Есть массив такого вида:

180
php и radiobutton

php и radiobutton

Как обработать код так, чтобы после проверки radiobutton не пересылало на другой сайт, а всё оставалось на том же, ну то есть когда ты обрабатываешь...

171