2015-12-11 3 views
0

Я создал класс для генерации 2 похожих, но очень разных отчетов. Для этого я использовал шаблон, который я нашел здесь: https://stackoverflow.com/a/29907649/3410196 Он использует абстрактный базовый класс, который содержит частные производные классы с общедоступными конструкторами, поэтому другой код никогда не может фактически получить доступ к конструкторам производного класса и создавать объекты только с использованием метода static Create() ,Абстрактный класс с частными производными классами: реализовать метод для некоторых

Теперь я столкнулся с проблемой: Все работает отлично, и я могу экспортировать отчеты и т.д. Но теперь я должен быть в состоянии экспортировать один отчетов в другом формате. Есть ли способ сделать этот метод доступным через базовый класс только для одного производного класса? В противном случае мне придется throw new NotImplementedException() или заставить свои пользователь использовать что-то вроде этого:

//Is actually multiReport (multireport:report) 
Report report = Report.Create(...); 
MemoryStream stream = (report as multireport).ExportOtherFormat(); 

Я сомневаюсь, что это возможно, но, может быть, есть способ!

+3

Создайте класс, ответственность которого заключается в экспорте ваших отчетов. Например, у вас может быть экспортер CSV, экспортер XML и т. Д. Этот класс возьмет ваш базовый класс отчета в качестве параметра. Создание и экспорт ваших отчетов, вероятно, являются двумя отдельными обязанностями, поэтому они должны быть в разных классах. –

+0

Действительно, я должен был реализовать это с самого начала, это было бы намного лучше. Однако уже слишком поздно, потому что слишком много приложений уже используют мою библиотеку. Извлеченный урок. Я думаю, –

+0

Не можете ли вы добавить еще один метод в свою библиотеку, который использует IExporter в качестве параметра? Затем вы можете создать несколько экспортеров, и пользователи вашей библиотеки могут затем сказать, как они хотят экспортировать, передав соответствующую реализацию экспортера?Например, public void Export (экспортер IExporter) –

ответ

0

В конце концов я пошел для решения (возможно, не самый лучший), чтобы сделать один классов государственных и разоблачить метод, как это, но его нет на других подклассов:

abstract class Report 
{ 
private Report() {} 

public abstract MemoryStream ExportPDF() { ... } 

public class ReportA : Report 
{ 
    public ReportA() { ... } 
    public override MemoryStream ExportPDF() {...} 
    public MemoryStream ExportCSV() {...} 
} 

private class ReportB : Report 
{ 
    public ReportB() { ... } 
    public override MemoryStream ExportPDF() {...} 
} 

public static Report Create() { ... } 
} 

Теперь только подкласс а имеет метод ExportCSV() и показывает его. Теперь люди могут вызвать конструктор, чтобы сделать подкласс A, но мне не очень нравится

1

Вы не можете сделать метод одного из подклассов видимым для внешних пользователей, потому что они создают экземпляр базового класса (то есть basereport, а не multireport). Они не смогут позвонить ExportOtherFormat, если они не знают, что они ищут экземпляр multireport, а не basereport.

Один из способов обойти эту проблему - это скрыть решение формата от пользователей. Сделать enum форматов и сделать ExportWithFormat метод, который принимает его:

[Flags] 
enum ReportFormat { 
    Simple = 1 
, Extended = 2 
, Special = 4 
, Multifile = 8 
} 

Добавьте эти свойства и методы базового класса:

public ReportFormat AvailableExportFormats { get {... } } 

public MemoryStream ExportWithFormat(ReportFormat format); 

Теперь ваш Multireport может вернуть специальный флаг для дополнительного формата что он поддерживает в AvailableExportFormats и производит надлежащий экспорт, когда этот флаг передается обратно ему в ExportWithFormat.

+0

Это будет работать, однако у меня есть и другие классы отчетов, которые реализуют мой интерфейс PDF и Excel, поэтому он станет непоследовательным. Я думаю, у меня нет другого выбора. Идея фабрики Darren - это то, что я должен был реализовать с самого начала, но сейчас уже слишком поздно. –

0

Если я вас правильно понял, что вам нужно что-то подобное, так что ReportB обеспечит новую реализацию метода экспорта:

abstract class Report 
{ 
    private Report() {} 

    public virtual MemoryStream Export() { ... } 

    private class ReportA : Report 
    { 
     public ReportA() { ... } 
    } 

    private class ReportB : Report 
    { 
     public ReportB() { ... } 
     new public virtual MemoryStream Export() { ... } 
    } 

    public static Report Create() { ... } 
} 
+0

Если я это сделаю, если я создам такой отчет, даже если это ReportA, он все равно покажет метод –

+1

. Мне показалось, что вам нужна только другая реализация метода Export. В случае, если вам нужен отдельный метод, я думаю, что предложение, сделанное @DarrenYoung, будет лучшим способом. –

+0

Да, действительно, должен был подумать об этом, когда я начал с этого проекта –

Смежные вопросы