Для перечисления типов отчетов нам нужно было где-то сохранить название отчета и имя файла, хранящего его разметку.
public enum ReportTypes
{
ComponentList = 1,
ComponentAudit = 2,
}
Самый простой вариант – добавить специальные методы, возвращающие по типу соответствующую информацию. Внутри методов, разумеется, торчит switch:
public static string GetReportTitle(ReportTypes type)
{
switch (type)
{
case ReportTypes.ComponentList:
return "Список компонентов";
case ReportTypes.ComponentAudit:
return "Аудит компонентов";
}
return string.Empty;
}
public static string GetReportFileName(ReportTypes type)
{
switch (type)
{
case ReportTypes.ComponentList:
return "ComponentList.frx";
case ReportTypes.ComponentAudit:
return "ComponentAudit.frx";
}
return string.Empty;
}
Первая очевидная проблема в этом коде – если вдруг мы передадим неверный тип отчета, то код об этом не скажет ничего. Исправить это не сложно:
public static string GetReportTitle(ReportTypes type)
{
switch (type)
{
case ReportTypes.ComponentList:
return "Список компонентов";
case ReportTypes.ComponentAudit:
return "Аудит компонентов";
default:
throw new ArgumentException("ReportTypes");
}
}
public static string GetReportFileName(ReportTypes type)
{
switch (type)
{
case ReportTypes.ComponentList:
return "ComponentList.frx";
case ReportTypes.ComponentAudit:
return "ComponentAudit.frx";
default:
throw new ArgumentException("ReportTypes");
}
}
Стало получше, но логика раскидана в трех местах – собственно в перечислении и в двух методах.
Можно попробовать собрать информацию с помощью класса, возвращающего все поля сразу:
public class ReportInfo
{
public string Title { get; set; }
public string FileName { get; set; }
}
public static ReportInfo GetReportInfo(ReportTypes type)
{
...
}
Теперь логика раскидана всего в двух местах, но мне не нравится и это. При добавлении нового типа отчета в перечисление нужно вспоминать, где же лежит метод, возвращающий информацию.
В .NET если очень мощный механизм, позволяющий решить этот вопрос – атрибуты. Создаем атрибут, хранящий информацию об отчете:
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
public class ReportAttribute : Attribute
{
public ReportAttribute(string title, string fileName)
{
this.ReportTitle = title;
this.ReportFile = fileName;
}
public string ReportTitle
{
get; protected set;
}
public string ReportFile
{
get; protected set;
}
}
Добавляем информацию прямо в перечисление:
public enum ReportTypes
{
[ReportAttribute("Список компонентов", "ComponentList.frx")]
ComponentList = 1,
[ReportAttribute("Аудит компонентов", "ComponentAudit.frx")]
ComponentAudit = 2,
}
Делаем класс, работающий с этими атрибутами:
public static class ReportTypesHelper
{
private static Type type = typeof(ReportTypes);
/// <summary>
/// Атрибут отчета для конкретного типа отчета
/// </summary>
public static ReportAttribute GetReportAttribute(ReportTypes reportType)
{
FieldInfo propInfo = type.GetField(reportType.ToString());
if (propInfo != null)
{
var attribs = propInfo.GetCustomAttributes(typeof(ReportAttribute), false) as ReportAttribute[];
if (attribs != null && attribs.Length > 0)
{
return attribs[0];
}
}
return null;
}
/// <summary>
/// Список отчетов
/// </summary>
/// <returns></returns>
public static IEnumerable<ReportAttribute> GetReportList()
{
var obj = Enum.GetValues(type);
foreach (ReportTypes item in obj)
{
yield return GetReportAttribute(item);
}
}
}
Все. Теперь можно легко получить и список всех отчетов и информацию о конкретном отчете. А все нужная информация хранится в одном месте. Если скорость получения информации критична (в моем случае это было совершенно не принципиально), можно сделать кэш и хранить один раз полученную информацию в нем.
No comments:
Post a Comment