Я пришел к препятствию в своей архитектуре приложения.Я только начал использовать шаблон посетителя для выполнения определенных алгоритмов на абстрактных объектах того типа, который я не знаю во время выполнения. Моя проблема в том, что мой алгоритм также зависит от типа вложенного абстрактного типа.
Позвольте мне проиллюстрировать, что я имею в виду:
У меня есть абстрактный класс DataSource,Из этого я реализую конкретные классы DataSourceReference и DataSourceExplicit.У меня также есть абстрактный класс Report (десериализованные метаданные), из которого я реализую конкретные классы ReportTypeA и ReportTypeB.Когда эти объекты созданы, их DataSource может быть любым расширяющим классом DataSource.
Мне нужны оба , фактический тип отчета и тип DataSource, чтобы я мог выполнить соответственно.Я могу получить согласованный тип отчета, используя шаблон посетителя, но не знаю, как сделать то же самое для DataSource впоследствии / также .
Я не могу посетить источник данных после посещения отчета, поскольку я потеряю конкретный тип отчета (так как вы должны были бы позволить ему принять базовый тип отчета: Принять (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);
}