Есть следующий класс
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++;
}
}
Возможно такой пример подойдет вам или натолкнет на мысль в нужном направлении.
Заведем базовый атрибут для кастомного форматирования:
[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();
}
Сборка персонального компьютера от Artline: умный выбор для современных пользователей