Мои коллеги и я собираем небольшую систему отчетности для интернет-магазина.Мы создали библиотеку по образцу репозитория, используя «отчеты» в качестве репозиториев и очень легкий сервисный слой для взаимодействия с указанными отчетами.Наш код прекрасно работает и довольно прост в использовании.Тем не менее, есть одна вещь, которая беспокоит меня лично: на уровне фабрики сервисов нам нужно дважды объявить наш тип возврата (это не выводится).Вот основа нашего проекта:
Интерфейс отчета
Это то, что используется в качестве наших «Хранилищ».Они принимают объекты доступа к данным, такие как классы-оболочки для соединения SQL / Oracle или API нашего Storefront.
internal interface IReport<T>
{
T GetReportData(dynamic options);
}
Фабрика репозитория
Это обеспечиваетпростой способ создать эти отчеты, зная тип.
internal interface IReportFactory
{
TR GenerateNewReport<T, TR>() where TR : IReport<T>;
}
internal class ReportFactory : IReportFactory
{
public ReportFactory()
{
// some initialization stuff
}
public TR GenerateNewReport<T, TR>() where TR : IReport<T>
{
try
{
return (TR)Activator.CreateInstance(typeof(TR));
}
catch(Exception ex)
{
// Logging
}
}
}
Пример отчета (репозиторий)
Вот как будет выглядеть отчет.Обратите внимание, что он возвращает DataTable и объявляется с этим в универсальном интерфейсе (он скоро появится).
internal class ItemReport : IReport<DataTable>
{
public DataTable GetReportData(dynamic options)
{
return new DataTable();
}
}
Служба отчетов
Облегченный сервис, который принимает отчет (репозиторий) и работает с ним.Легко, но позволяет легко выполнять модульное тестирование и тому подобное, и если мы когда-нибудь захотим добавить дополнительную обработку после получения отчетов, это будет легко сделать.
public interface IReportService<T>
{
T GetReportData(dynamic options);
}
public class ReportService<T> : IReportService<T>
{
private readonly IReport<T> _report;
public ReportService(IReport<T> report)
{
_report = report;
}
public T GetReportData(dynamic options)
{
return _report.GetReportData(options);
}
}
СлужбаФабрика
У нас есть фабрика обслуживания, настроенная как абстрактный класс (потому что все фабрики обслуживания должны будут создать фабрику отчетов), форсируя конструктор по умолчанию:
public abstract class ReportServiceFactory
{
protected IReportFactory ReportFactory;
protected ReportServiceFactory(connection strings and other stuff)
{
ReportFactory = new ReportFactory(connection strings and other stuff);
}
}
Мы можемзатем создайте отдельные фабрики обслуживания на основе функции.Например, у нас есть фабрика обслуживания «стандартный отчет», а также фабрики по обслуживанию клиентов.Реализация здесь, где мой вопрос.
public class SpecificUserServiceFactory : ReportServiceFactory
{
public SpecificUserServiceFactory(connection strings and other stuff) : base(connection strings and other stuff){}
public IReport<DataTable> GetItemReport()
{
return new ReportService<DataTable>(ReportFactory.GenerateNewReport<DataTable, ItemReport>());
}
}
Почему я должен быть настолько многословным при создании фабрики сервисов?Я объявляю тип возврата дважды.Почему я не могу сделать что-то вроде этого:
return new ReportService(ReportFactory.GenerateNewReport<ItemReport>());
Обратите внимание, что я не объявляю DataTable в этом;Я думаю, что это следует из того факта, что ItemReport является IReport.Будем весьма благодарны за любые предложения о том, как заставить его работать таким образом.
Извините за такое длинное объяснение, чтобы задать такой простой вопрос, но я решил, что весь код поддержки поможет придуматьрешение.Еще раз спасибо!