Я столкнулся с препятствием в архитектуре моего приложения. Я только начал использовать шаблон посетителя для выполнения определенных алгоритмов для абстрактных объектов, тип которых я не знаю во время выполнения. Моя проблема в том, что мой алгоритм также зависит от типа вложенного абстрактного типа.
У меня есть абстрактный класс DataSource. Исходя из этого, я реализую конкретные классы DataSourceReference и DataSourceExplicit. У меня также есть абстрактный класс Report (десериализованные метаданные), из которого я реализую конкретные классы Report ReportTypeA и ReportTypeB. Когда эти объекты созданы, их DataSource может быть любым расширяющимся классом DataSource.
Мне нужны и , и фактический тип отчета, и тип источника данных, чтобы я мог выполнять соответствующие действия. Я могу получить отчет о концерте, используя шаблон посетителя, но не знаю, как сделать то же самое для DataSource впоследствии / также .
Я не могу посетить DataSource после посещения отчета, потому что я потеряю конкретный тип отчета (поскольку вам придется позволить ему принимать базовый тип отчета: Accept (SomeDataSourceVisitor d, MetaReport m) или перегрузить для каждого возможный тип отчета, который противоречит цели шаблона посетителя.Видишь мою проблему?
Есть идеи? Я бы не хотел использовать динамический, так как это не потребует от разработчиков новых типов отчетов, чтобы диспетчер (посетитель) поддерживал новый отчет.
public abstract class DataSource
{
}
public class DataSourceReference : DataSource
{
// reference thing(s)
}
public class DataSourceExplicit : DataSource
{
// explicit thing(s)
}
public abstract class Report
{
// some shared Report attribute(s)
// ...
public DataSource DataSource { get; set; }
public abstract FinalReport Execute(IReportExecutionDispatcher d);
}
public class ReportA : Report
{
// ReportA specific attribute(s)
// ...
public override Execute(IReportExecutionDispatcher d)
{
d.ExecuteReport(this);
}
}
public class ReportB : Report
{
// ReportB specific attribute(s)
// ...
public override Execute(IReportExecutionDispatcher d)
{
d.ExecuteReport(this);
}
}
public interface IReportExecutionDispatcher
{
FinalReport ExecuteReport(ReportA);
FinalReport ExecuteReport(ReportB);
}