Экспертная система Delphi.int.ru

Сообщество программистов
Общение, помощь, обмен опытом

Логин:
Пароль:
Регистрация | Забыли пароль?

Delphi.int.ru Expert

Другие разделы портала

Переход к вопросу:

#   

Статистика за сегодня:  


Лучшие эксперты

Подробнее »



Вопрос # 3 529

/ вопрос открыт /

Здравствуйте, эксперты!
Когда жму кнопку один, программа должна найти пути всех DLL в папке Plugins и получить их типа и имена, а так же имена файлов.

Когда жму 2-ю кнопку, в ЛистБокс надо вывести имена всех плагинов. Почему-то не могу. Прикрепляю проект, подскажите в чем ошибка плиз, я классы первый раз пишу, скорее всего что-то недопонял. Заранее спасибо!

К вопросу прикреплён файл. Загрузить » (срок хранения: 60 дней с момента отправки вопроса)

webkent Вопрос ожидает решения (принимаются ответы, доступен мини-форум)

Вопрос задал: webkent (статус: 2-ой класс)
Вопрос отправлен: 15 декабря 2009, 10:47
Состояние вопроса: открыт, ответов: 1.

Ответ #1. Отвечает эксперт: Вадим К

Здравствуйте, webkent!
Посмотрел код. в коде есть откровенное непонимание. например строка

ListBox1.Items:=PL.Items.GetNames
Это очень плохая конструкция. Если оно заработает, то это будет странно... Правильно как минимум так
ListBox1.Items.Clear;
ListBox1.Items.AddString(PL.Items.GetNames)
правда, в данном коде это не поможет. Потому что реализация GetNames плохая. В ней явная утечка памяти. Что бы избежать утечку памяти, надо либо сделать метод вида
procedure GetNames(sl:TStrings);
и вызывать как
Pl.items.GetNames(ListBox1.items);

В середине метода можно напрямую обращаться к строкам ListBox через параметр sl (то есть просто sl.Add(строка); Реализацию внутри пишите сами.

Реализация GetFileNames ещё веселее - там вызываются методы не созданного объекта. И GetTypes тоже:)
пойдем дальше
List:array[0..MaxListSize] of TPlugin
лучше писать
List:TList; плюс в коде будет пара приведений. Но зато не надо будет извращаться с SetLength и думать, как удалить элемент с середины списка.
MaxListSize... это интересная конструкция. Если бы знали, как она получается, не использовали бы. посмотрите на значение этой константы. Пара таких классов и прощай память. (подсказка const MaxListSize = Maxint div 16; Maxint = 2 в 31 степени минус 1.)
конструкцию
Procedure log(MSG:Tstrings);
    var i:integer;
begin
{...............................................................................}
  if MSG.Count=1 then
    MSG[0]:=DateTimeToStr(Now)+'  '+MSG[0]
  else
    for i:=0 to MSG.Count-1 do
      MSG[i]:=DateTimeToStr(Now)+'  '+MSG[i];
{...............................................................................}
  MSG.SaveToFile('PluginsLog.txt');
  end;

долго рассматривал. неужели условие действительно нужно? сомневаюсь. Там только цикл нужен.

И теперь вернемся к основном коду. имеем метод Initialize. Я так подозреваю, что это конструктор. Но для объекта Pl настоящий конструктор не вызывается... печально. Поэтому работать сей код в принципе не должен.
Код кнопки должен выглядеть где то так
Pl:=TPlugins.Create;
PL.Initialize;
Pl.items.GetNames(ListBox1.items);
Pl.Free;
и не надо две кнопки:) исправте код, а там будет видно, что дальше делать.

Ответ отправил: Вадим К (статус: Академик)
Время отправки: 15 декабря 2009, 23:19
Оценка за ответ: 5


Мини-форум вопроса

Всего сообщений: 14; последнее сообщение — 18 декабря 2009, 16:09; участников в обсуждении: 4.
IlluminatI

IlluminatI (статус: 2-ой класс), 15 декабря 2009, 21:10 [#1]:

webkent, получить "их типа и имена", это в смысле расширение и имя? имя понятно зачем получать, а вот расширение зачем? Вы указали, что нужно получить список dll, значит и расширения у них будут dll. Или тут что-то другое имеется ввиду?
Мережников Андрей

Мережников Андрей (статус: Абитуриент), 15 декабря 2009, 21:26 [#2]:

to IlluminatI: "их типа и имена" это что-то другое, отличное от имени файла и расширения потому, что далее по тексту вопрошающий говорит об именах файлов. Так что телепаты отдыхают...
webkent

webkent (статус: 2-ой класс), 16 декабря 2009, 08:36 [#3]:

2 Вадим К:
Спасибо за ответ!

"Это очень плохая конструкция. Если оно заработает, то это будет странно... Правильно как минимум так. "

почему? А если я хочу не добавить в листбокс, а присвоить ему значения, возвращенные функцией. Конечно, можно и GetNames(sl:TStrings), но чем такой вид лучше?

По поводу цикла, вы снова правы, убрал условие.


"List:array[0..MaxListSize] of TPlugin"
Тут я согласен, но, можно ли вызывать из TList методы его членов типа TPlugin? Допустим вот так реально сделать, используя TList?:

var s:string;
s:=TList[n].GetName();
Если можно, то как это сделать? Если я пишу так:
Items:TList;
То потом не могу вызвать методы отдельного TPlugin:
PL.Items[n].КакойтоМетод; //Не работает. Как правильно, подскажите?

По поводу конструктора, а в процедуре Initialize я писал такую строку Self:=TPlugin.Create. Почему-то думал, что должно работать, но сейчас и сам понимаю что ошибся.


Вот версия, в которой я исправил то что вы написали, кроме array of TPlugin т.к. не знаю как правильно использовать их методы из TList: http://webfile.ru/4164853

Спасибо огромное за ответы, очень помогаете развиваться!
Вадим К

Вадим К (статус: Академик), 18 декабря 2009, 00:02 [#4]:

Расскажу о некоторых моментах, может улучшит Ваше понимание.
Итак, пусть у нас есть приватное поле list:TList;
итак, в конструкторе нам надо это создать
list:=TList.create;
в деструкторе соответственно почистим вложенные объекты и сам лист
for i:=0 to list.count-1 do
  TPlugin(list[i]).Free;
list.free;

Теперь напишем метод добавления
function TPlugins.add:TPlugin;
begin
  result := TPlugin.Create;
  list.add(result);
  //тут можно заполнить дефолтные параметры нового элемента
end;
использовать так
var p:TPlugin;
begin
//...
p := pl.Add();//эта строка фактически конструктор и добавление в список
p.метод(); //а теперь можно вызывать методы нового элемента
//...
end;
поехали дальше. Сделаем удобное обращение к элементам
в описании класса
private
procedure GetPrivate(index:integer):TPlugin;
public
property Items(index:integer):TPlugin read GetPlugin;default;
и реализация
procedure TPlugins.GetPrivate(index:integer):TPlugin;
begin
  if (index < 0) or (index >= list.count)
    ShowMessage('ОШИБКА, индекс за пределами!!!!')// тут конечно лучше сгенерировать исключение.
  else
    result := TPlugin(list[index]);
end;
теперь можно писать так
pl.items[1].метод();
а благодаря слову default даже так
pl[2].метод();
не правда, красиво получается?

поехали дальше, напишем метод Count, что бы выводило кол-во элементов
//описание класса
public
  function Count:integer;
 
//....
//реализация
function TPlugins.Count():integer;
begin
  result := list.Count;
end;
метод "удалить элемент по индексу"
//реализация
procedure TPlugins.Delete(index:integer);
begin
  TPlugin(list[index]).free;
  list.delete(index);
end;
Думаю, другие методы себе сами напишите.
Для класса TList такое включение предпочтительней наследования. Почему? да просто наружу выносятся только те методы, которые реально надо. Во вторых - полный контроль над ним. Никакой другой код не повлияет.
В третьих. припустим, что TList оказался плохим решением, а у нас написана большая программа. Мы только заменим в одном модуле, перепишем несколько методов и готово.
Как только освоите эту методику, многие куски кода можно будет красиво упрощать. Можно будет делать классы с заданной функциональностью и потом легко управлять ими.

комментарии к предыдущему посту.
код вида
s:=TList[n].GetName();
не будет работать. потому что у TList нет классового метода с default. А как писать правильно - я писал выше.
Галочка "подтверждения прочтения" - вселенское зло.
webkent

webkent (статус: 2-ой класс), 18 декабря 2009, 08:56 [#5]:

Спасибо огромное! Вот, как раз то чего мне так не хватало:
TPlugin(list[index]);

Начинаю писать. По возможности буду помогать другим тут на сайте.
webkent

webkent (статус: 2-ой класс), 18 декабря 2009, 11:42 [#6]:

Кстати, тут проблемка, выдает Access violation на строчках

Result:=TPlugin.Create;
Items.Add(Result); --> вот именно при выполнении этой строки.

То же самое при таком виде:
Items.Add(TPlugin.Create);

В чем может быть дело? Items : TPList : TList
Вадим К

Вадим К (статус: Академик), 18 декабря 2009, 11:49 [#7]:

не могу понять суть строки Items : TPList : TList
Я таких множественных определений не понимаю.

Хотя, если все делано по моему коду, то подозреваю либо рекурсию, либо ....
Приводите полный код. и лучше выкладывайте сразу сюда
https://www.delphi-int.ru/code/paste/
Галочка "подтверждения прочтения" - вселенское зло.
webkent

webkent (статус: 2-ой класс), 18 декабря 2009, 12:03 [#8]:

Items:TPList:TList - это не код, от себя написал, что бы показать, что Items идет от TList.

Вот
https://www.delphi-int.ru/code/22b4dd0f

Строка номер 45. Заранее прошу прощения за то что я такой ламер =)
webkent

webkent (статус: 2-ой класс), 18 декабря 2009, 12:06 [#9]:

там рекурсии нет, просто у TPlugins есть своя ф-ция Add, а у Items - своя.
webkent

webkent (статус: 2-ой класс), 18 декабря 2009, 12:11 [#10]:

Простите дурака, уже допер, не прописал Items:=TPList.Create.
Вадим К

Вадим К (статус: Академик), 18 декабря 2009, 12:16 [#11]:

Первое. я писал, что наследоваться от TList - плохая затея. Не предназначен этот класс для наследования. Поэтому следует исключить промежуточный класс.
Второе. А ошибка возникает на законном месте. Я же писал - надо конструктор! Или просто не знаем, как выглядит конструктор?
type
TPlugins = class
private
  list:TList;
public
  constructor Create;
  destructor Destroy; override;
end;
 
constructor TPlugins.Create;
begin
Items := TList.Create;
end;
 
destructor TPlugins.Destroy;
begin
for i:=0 to list.count-1 do
  TPlugin(list[i]).Free;
list.free;
end;
Галочка "подтверждения прочтения" - вселенское зло.
webkent

webkent (статус: 2-ой класс), 18 декабря 2009, 12:26 [#12]:

Не знал, спасибо =)
Вадим К

Вадим К (статус: Академик), 18 декабря 2009, 13:06 [#13]:

Ну так надо определить свой конструктор:) Точно также, как я для TPlugins написал. Но конструктор TObject все равно надо вызывать:) правда он часто неявно вызывается или явно через ключевое слово inherited;
Галочка "подтверждения прочтения" - вселенское зло.
webkent

webkent (статус: 2-ой класс), 18 декабря 2009, 16:09 [#14]:

Да, дело уже продвигается по немногу, вроде бы многое стало понятно.

Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.

Версия движка: 2.6+ (26.01.2011)
Текущее время: 22 февраля 2025, 11:46
Выполнено за 0.06 сек.