Параметры метода (строки) или (строки+картинки)
Модератор: Модераторы
Параметры метода (строки) или (строки+картинки)
Всем привет!
Возникла такая задача. Есть класс, который строит html файл по кусочкам. Есть метод, который добавляет строку таблицы. В ячейке может быть только текст, но может быть текст + изображения. Вот я задумался, как проще и универсальнее это организовать. Пока придумал такой вариант. Объявляются два перегруженных метода AddRow. В сигнатуре первого в параметрах только массив строк. В сигнатуре второго - массив строк и массив (список, без разницы, любая коллекция в общем) изображений как объектов. А ячейка, в которую необходимо будет вставлять именно изображение, определяется по какому-нибудь управляющему ключу в первом массиве строк, например, <?IMG?>
И сразу же подумалось, возможно ли такое в C# более простым способом - в параметрах передается массив объектов переменной длинны AddRow(params object[] cells), внутри метод проверяет тип каждого элемента массива - для string своя обработка, для изображений - своя.
Возникла такая задача. Есть класс, который строит html файл по кусочкам. Есть метод, который добавляет строку таблицы. В ячейке может быть только текст, но может быть текст + изображения. Вот я задумался, как проще и универсальнее это организовать. Пока придумал такой вариант. Объявляются два перегруженных метода AddRow. В сигнатуре первого в параметрах только массив строк. В сигнатуре второго - массив строк и массив (список, без разницы, любая коллекция в общем) изображений как объектов. А ячейка, в которую необходимо будет вставлять именно изображение, определяется по какому-нибудь управляющему ключу в первом массиве строк, например, <?IMG?>
И сразу же подумалось, возможно ли такое в C# более простым способом - в параметрах передается массив объектов переменной длинны AddRow(params object[] cells), внутри метод проверяет тип каждого элемента массива - для string своя обработка, для изображений - своя.
Изображения можно забить в строку (гугли в сторону base64 кодировки) - т.е. весь файл с картинкой кодируется и внедряется в параметр src тега img.
Может, пригодится.
Может, пригодится.
А строки как передаются в параметрах - по значению или по ссылке? Да и в любом случае, мне кодировать изображение в строку не подходит. Мне нужно передать строителю именно сами изображение как объект. Строитель html сам его сохранит рядом с файлом .html в папочке, строитель doc внедрит в текст, строитель pdf тоже как-то по своему обработает. Вот я к чему. А сначала преобразовывать в строку, а потом из строки снова преобразовывать в объект или файл это не айс как-то.
params object[] до некоторой степени имитируется array of const. Можно как-нибудь так сделать:
Или вместо array of const принимать array of TLineDesc, где TLineDesc — вспомогательная запись с теми же line и images, + перегруженные функции-конструкторы TLineDesc. Тогда такой же вызов будет выглядеть как
А если для случая строки без картинок определить operator :=(const s: string): TLineDesc, то будет работать и
Код: Выделить всё
procedure AddRow(const params: array of const);
var
i: integer;
line: string;
images: array of TPicture;
begin
i := 0;
while i < length(params) do
begin
// строка
if params[i].VType <> vtAnsiString then raise ...;
line := string(params[i].VAnsiString);
inc(i);
// возможно, картинки для этой строки
images := nil;
while (i < length(params)) and (params[i].VType = vtObject) do
begin
SetLength(images, length(images) + 1);
images[High(images)] := params[i].VObject as TPicture;
inc(i);
end;
// сделать что-то с line и images
end;
end;Код: Выделить всё
AddRow(['строка 1', Image1, 'строка 2 без картинок', 'строка 3 с двумя картинками', Image3_1, Image3_2])Или вместо array of const принимать array of TLineDesc, где TLineDesc — вспомогательная запись с теми же line и images, + перегруженные функции-конструкторы TLineDesc. Тогда такой же вызов будет выглядеть как
Код: Выделить всё
AddRow([
RowLine('строка 1', Image1),
RowLine('строка 2 без картинок'),
RowLine('строка 3 с двумя картинками', [Image3_1, Image3_2])
])А если для случая строки без картинок определить operator :=(const s: string): TLineDesc, то будет работать и
Код: Выделить всё
AddRow([
RowLine('строка 1', Image1),
'строка 2 без картинок', // для неявного приведения вызовется operator :=
RowLine('строка 3 с двумя картинками', [Image3_1, Image3_2])
])runewalsh писал(а):params object[] до некоторой степени имитируется array of const. Можно как-нибудь так сделать:
Если есть минутка, посмотрите мой вариант. Ошибка SIGSEV на строке
Код: Выделить всё
HTMLDoc.AddRow(['1',JPEGimg1]);то есть именно тогда, когда в параметрах передается массив со строкой и картинкой типа TJPEGImage...
репозиторий
Проверяй vt на vtAnsiString, прежде чем приводить. Вообще, проверяй всё, что можно неверно передать, и бросайся исключениями, если что-то не так. В данном случае '1' передаётся как vtChar, отсюда и краш.
>VObject.ClassName = 'TJPEGImage'
VObject is TJPEGImage.
У тебя в коде есть ещё ошибки, например, деструктор объекта называется не Free, а Destroy и должен быть отмечен override, иначе код видане вызовет деструктор THTMLDocBuilder. Free — это невиртуальная функция, которая проверяет ссылку на nil и вызывает Destroy (так что проверка в if a <> nil then a.Free не нужна).
>VObject.ClassName = 'TJPEGImage'
VObject is TJPEGImage.
У тебя в коде есть ещё ошибки, например, деструктор объекта называется не Free, а Destroy и должен быть отмечен override, иначе код вида
Код: Выделить всё
var
o: TObject;
begin
o := THTMLDocBuilder.Create;
o.Free;
end;УПС, ложная тревога, всё заработало.
Когда подаешь в массив ['1'...] - то есть элемент с одним символом, он его воспринимает как char, а не ansistring
Косяк был в этом
С картинкой - имеет значение регистр названия при сопоставлении имени класса. Например, в коде название TJPEGImage, а ClassName выдает TJpegImage
Добавлено спустя 1 минуту 57 секунд:
Да, это моя любимая ошибка от торопливости, который год...
Спасибо) видишь, если дать время, то я и сам со всем почти разберусь))
Когда подаешь в массив ['1'...] - то есть элемент с одним символом, он его воспринимает как char, а не ansistring
Косяк был в этом
С картинкой - имеет значение регистр названия при сопоставлении имени класса. Например, в коде название TJPEGImage, а ClassName выдает TJpegImage
Добавлено спустя 1 минуту 57 секунд:
runewalsh писал(а):У тебя в коде есть ещё ошибки, например, деструктор объекта называется не Free, а Destroy и должен быть отмечен override
Да, это моя любимая ошибка от торопливости, который год...
Спасибо) видишь, если дать время, то я и сам со всем почти разберусь))
