Я заинтересован в создании настраиваемой опции экспорта в Excel для моего отчета в ReportViewer. Это в основном потому, что я хочу отключить pdf, и я сделал это с помощью:
ReportViewer1.ShowExportControls = false;
Так как в ReportViewer нет возможности отключить какую-либо конкретную функцию экспорта (например, pdf, но не excel). Вот мой (слегка) модифицированный код ниже. В идеале мне бы хотелось что-то похожее на предыдущие параметры экспорта, где я могу сохранить файл в любое место, которое я хочу.
РЕДАКТИРОВАТЬ: Псевдослучайный образец должен быть сгенерирован. Существует несколько способов / или алгоритмов для создания различного контента. Все алгоритмы будут генерировать список символов (но это может быть что угодно ...
Установка:
Псевдослучайный образец должен быть сгенерирован. Существует несколько способов / или алгоритмов для создания различного контента. Все алгоритмы будут генерировать список символов (но может быть и любым другим) ... важная часть заключается в том, что все они возвращают одинаковые типы значений и нуждаются в одинаковых типах входных аргументов.
Это должно быть можно вызвать метод GetRandomPattern (), который будет использовать случайный один из алгоритмов при каждом его вызове.
Мой первый подход состоял в том, чтобы поместить каждый алгоритм в его собственную функцию и выбирать случайный из них каждый раз, когда GetRandompattern () называется. Но я не придумал другого способа выбора между ними, кроме заявления о переключении, которое было бы неудобным, безобразным и негибким.
class PatternGenerator{
public:
list<char> GetRandomPattern();
private:
list<char>GeneratePatternA(foo bar);
list<char>GeneratePatternB(foo bar);
........
list<char>GeneratePatternX(foo bar);
}
Как можно было бы выбрать случайную функцию GeneratePattern при каждом вызове метода GetRandomPattern () ?
Или весь класс должен быть оформлен по-другому?
Большое спасибо
Спасибо за ваш большой вклад. Я решил использовать указатели на функции, главным образом потому, что я не знал их раньше, и они кажутся очень мощными, и это был хороший шанс познакомиться с ними, но также потому, что это экономит мне много строк кода.
Если бы я использовал Ruby / Java / C #, я бы выбрал предложенный шаблон проектирования стратегии; -)
class PatternGenerator{
typedef list<char>(PatternGenerator::*createPatternFunctionPtr);
public:
PatternGenerator(){
Initialize();
}
GetRandomPattern(){
int randomMethod = (rand()%functionPointerVector.size());
createPatternFunctionPtr randomFunction = functionPointerVector.at( randomMethod );
list<char> pattern = (this->*randomFunction)();
return pattern;
}
private:
void Initialize(){
createPatternFunctionPtr methodA = &PatternGenerator::GeneratePatternA;
createPatternFunctionPtr methodB = &PatternGenerator::GeneratePatternB;
...
functionPointerVector.push_back( methodA );
functionPointerVector.push_back( methodB );
}
list<char>GeneratePatternA(){
...}
list<char>GeneratePatternB(){
...}
vector< createPattern > functionPointerVector;
Читаемость не намного хуже, чем была бы с решением шаблона проектирования, это просто чтобы добавить новые алгоритмы, арифметика указателей заключена в класс, это предотвращает утечки памяти, и это очень быстро и эффективно ...
Создайте один класс для каждого алгоритма, каждый из которых подклассифицирует класс генератора. Поместите экземпляры этих объектов в список. Выберите один случайным образом и используйте его!
В более общем случае, если вы начинаете создавать несколько альтернативных методов с одинаковой сигнатурой, что-то кричит вам "поместите нас в классы-братья" :)
Update Не могу удержаться от того, чтобы еще немного поспорить за объектно-ориентированное решение после того, как пришло предложение с указателями
Вы можете создать массив указателей функций. Это избавляет от необходимости создавать целую кучу различных классов, хотя вам все равно придется назначать указатели функций элементам массива. В любом случае, если вы сделаете это, будет много повторяющихся строк. В вашем примере они находятся в методе GetRandomPattern. В моем - в конструкторе PatternGenerator.
#define FUNCTION_COUNT 24
typedef list<char>(*generatorFunc)(foo);
class PatternGenerator{
public:
PatternGenerator() {
functions[0] = &GeneratePatternA;
functions[1] = &GeneratePatternB;
...
functions[24] = &GeneratePatternX;
}
list<char> GetRandomPattern() {
foo bar = value;
int funcToUse = rand()%FUNCTION_COUNT;
functions[funcToUse](bar);
}
private:
generatorFunc functions[FUNCTION_COUNT];
}
Одним из способов избежать переключаемого кодирования является использование шаблона разработки стратегии. Например:
class IRandomPatternGenerator { public: virtual list<int> makePattern(foo bar); }; class ARandomPatternGenerator : public IRandomPatternGenerator { public: virtual list<int> makePattern(foo bar) { ... } }; class BRandomPatternGenerator : public IRandomPatternGenerator { public: virtual list<int> makePattern(foo bar) { ... } };
Затем вы можете выбрать конкретный алгоритм в зависимости от типа времени выполнения вашего экземпляра RandomPatternGenerator. (В качестве примера предлагается создание списка наподобие nicolas78)