| 
| 
 | Вопрос # 3 529/ вопрос открыт / | 
 |  Здравствуйте, эксперты!Когда жму кнопку один, программа должна найти пути всех DLL в папке Plugins и получить их типа и имена, а так же имена файлов.
 
 Когда жму 2-ю кнопку, в ЛистБокс надо вывести имена всех плагинов. Почему-то не могу. Прикрепляю проект, подскажите в чем ошибка плиз, я классы первый раз пишу, скорее всего что-то недопонял. Заранее спасибо!
 К вопросу прикреплён файл. Загрузить » (срок хранения: 60 дней с момента отправки вопроса) 
|  |   Вопрос задал: 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 (статус: 2-ой класс), 15 декабря 2009, 21:10 [#1]:webkent, получить "их типа и имена", это в смысле расширение и имя? имя понятно зачем получать, а вот расширение зачем? Вы указали, что нужно получить список dll, значит и расширения у них будут dll. Или тут что-то другое имеется ввиду? |  
|   | Мережников Андрей (статус: Абитуриент), 15 декабря 2009, 21:26 [#2]:to IlluminatI: "их типа и имена" это что-то другое, отличное от имени файла и расширения потому, что далее по тексту вопрошающий говорит об именах файлов. Так что телепаты отдыхают... |  
|   | 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 (статус: 2-ой класс), 18 декабря 2009, 08:56 [#5]:Спасибо огромное! Вот, как раз то чего мне так не хватало: TPlugin(list[index]);
 
 Начинаю писать. По возможности буду помогать другим тут на сайте.
 |  
|   | 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 (статус: 2-ой класс), 18 декабря 2009, 12:03 [#8]:Items:TPList:TList - это не код, от себя написал, что бы показать, что Items идет от TList. 
 Вот
 https://www.delphi-int.ru/code/22b4dd0f
 
 Строка номер 45. Заранее прошу прощения за то что я такой ламер =)
 |  
|   | webkent (статус: 2-ой класс), 18 декабря 2009, 12:06 [#9]:там рекурсии нет, просто у TPlugins есть своя ф-ция Add, а у Items - своя. |  
|   | 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 (статус: 2-ой класс), 18 декабря 2009, 12:26 [#12]:Не знал, спасибо =) |  
|   | Вадим К (статус: Академик), 18 декабря 2009, 13:06 [#13]:Ну так надо определить свой конструктор  Точно также, как я для TPlugins написал. Но конструктор TObject все равно надо вызывать  правда он часто неявно вызывается или явно через ключевое слово inherited; Галочка "подтверждения прочтения" - вселенское зло. |  
|   | webkent (статус: 2-ой класс), 18 декабря 2009, 16:09 [#14]:Да, дело уже продвигается по немногу, вроде бы многое стало понятно. |  Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте. |