Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Для новичков > RegisterCLass. Как зарегистрировать класс?


Автор: Avers 3.12.2008, 15:22
Есть некоторый класс
Код

  TMyClass = class(TObject)
  ...
  end;

При инициализации модуля нужно зарегистрировать этот класс. Проблема в том, что для процедуры RegisterClass требуется TPersistenClass или его потомки...... 
Какие есть решения??
Help!

Автор: CodeMonkey 3.12.2008, 15:26
Цитата(Avers @  3.12.2008,  15:22 Найти цитируемый пост)
При инициализации модуля нужно зарегистрировать этот класс.

Зачем?

Цитата(Avers @  3.12.2008,  15:22 Найти цитируемый пост)
Какие есть решения??

Смотря какой задачи.

Цитата(Avers @  3.12.2008,  15:22 Найти цитируемый пост)
Проблема в том, что для процедуры RegisterClass требуется TPersistenClass или его потомки.

А вы знаете, зачем нужна RegisterClass?

Автор: Avers 3.12.2008, 15:26
Напрашивается решение 
Код

  TMyClass = class(TPersisten)
  ...
  end;


но должны быть и другие решения (имхо);

Добавлено через 4 минуты и 24 секунды
Это модуль из пакета. Поэтому приходится прописывать в разделе инициализации регистрацию класса. 


Цитата(CodeMonkey @  3.12.2008,  15:26 Найти цитируемый пост)
А вы знаете, зачем нужна RegisterClass?

Признаюсь - смутно представляю....  хотя суть, имхо, очевидна.

Цитата(CodeMonkey @  3.12.2008,  15:26 Найти цитируемый пост)
Смотря какой задачи.

Нужно зарегистрировать TMyCkass))

Автор: CodeMonkey 3.12.2008, 16:00
Цитата(Avers @  3.12.2008,  15:26 Найти цитируемый пост)
Это модуль из пакета. Поэтому приходится прописывать в разделе инициализации регистрацию класса. 

Почеееемууу?

Цитата(Avers @  3.12.2008,  15:26 Найти цитируемый пост)
Нужно зарегистрировать TMyCkass))

Зачеееем?

RegisterClass регистрирует класс для системы персистентности Delphi. Зарегистрированный класс можно сохранять в поток и загружать из него вызовами TStream.WriteComponent/ReadComponent.

Что значит зарегистрировать класс, не являющийся потомком TPersistent? В контексте RegisterClass эта операция лишена смысла.

Аналогия: в дверной косяк вставляются двери. 

Вы говорите: При инициализации модуля нужно вставить в косяк окно. Проблема в том, что в дверной косяк можно вставить только дверь. 
Какие есть решения??

Я: зачем вы хотите вставить в дверной косяк окно? В дверной косяк можно вставить только дверь. Поэтому либо берите дверь, либо используйте оконный проём.

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

Ясна аналогия? Поэтому скажите, что вам нужно - так и ответ будет корректнее.

Автор: bems 3.12.2008, 20:37
вот здесь хорошо описана Ваша проблема http://gunsmoker.blogspot.com/2008/10/x-y-z.html

Автор: Avers 4.12.2008, 12:45
CodeMonkey, спс за ответ)) ценю чувство юмора. Нелепость желаемого мною - теперь очевидна.
Теперь по порядку.
В пакете bpl реализовывается несколько функций (подробнее по вызову различных сообщений). Почему пакет bpl?.... примем как нечто свыше.
Далее программист в своей программе предусматривает загрузку пакета и радостно пользуется готовыми сообщниями.
Сообщения реализованы как четрые формы, соответсвенно, четыре отдельных модуля. Есть модуль, в котором реализуется простейший класс, поддерживающий некоторый интерфейс (например IMyInterface), чтобы программист мог работать с пакетом. Этот модуль подключает те четрые с формами, вызывает при необходимости нужный месседж. В нем же есть класс (т.е. тот класс который будет обрабатывать запросы от приложения и командовать выводом сообщений, т.е. тупо посредник.
Код

TMyClass = class(TInterfacedObject, IMyInterface)
pulic
  ShowMsg1(Param1: type1);
  ...
  ShowMsg4(Param2: type4);
end;

В программе нам нужно лишь проверить
GetClass('TMyClass') и поддержку интерфейса.

Вот я и подумал, зачем мне чего-то мудрить с другими классами, если достаточно TObject для реализации задуманного. 

вот такая вот несложная задача. Просто не хотелось базировать свой на TPersisten.

Добавлено через 8 минут и 2 секунды
Если вы считаете, что ошибка была еще раньше, например при выборе конкретной реализации (имею ввиду интерфейсы). То предложите другой способ общения приложения с пакетом.
Класс с абстрактными методами не катит, ибо с наследованием и изменением функциональности больше проблем, чем при использовании интерфейсов. 

Автор: CodeMonkey 4.12.2008, 17:15
Что-то я не до конца понял.

Цитата(Avers @  4.12.2008,  12:45 Найти цитируемый пост)
В программе нам нужно лишь проверитьGetClass('TMyClass') и поддержку интерфейса.

Вот это можете пояснить? Зачем это нужно делать в программе? 

Можете подробнее рассказать? Я так и не понял, что из этого у вас лежит в пакете, что - вне его. Откуда главная программа возьмёт класс или интерфейс (и что она вообще должна брать)?

Автор: Avers 5.12.2008, 05:21
Реализуется несложное взаимодействие.
Есть некоторое Приложение и есть неокторая Форма. По некоторым причинам нужно отделить Форму от Приложения. Упаковываем Форму в пакет bpl.
Пакет:
модуль формы содержит форму и некоторую функцию ShowForm. 
модуль Main использует модуль формы и содержит класс (MyClass), управляющий формой (точнее - класс юзает ShowForm). Класс создается, поскольку форм может быть несколько.... короч, так удобнее (мне лично удобнее и разобраться проще и код править проще).

Теперь связываем Приложение и Пакет.
Для этого пишем интерфейс (Объект - реальзизация = объявление функции ShowForm).

Интерфес поддерфивает MyClass и об этом интерфейсе "знает" Приложение.
Таким образом мы получаем свободу при реализации Формы.

Теперь из программы управляем формой через специально написанный интерфейс, а точнее - запускаем процедуру ShowForm=)))) Для этого:
обявляем некоторый объект, загружаем класс из пакета и создаем объект.
Если бы 
Код

MyClass = class(TForm)

то
Код

 MyObject: TForm;
 MyInterface: TMyInterface // интерфейс с процедурой ShowForm
 ...
 MyObject := TFormClass(GetClass('TMyClass')).Create(nil);
 if MyObject.GetInterface(TMyInterface,MyInterface) then
   MyInterface.ShowForm; // вызвали процедуру, т.е. показали форму хранящуюся в пакете

Вот.
В моем случае форм 4 (это пока, дальше - больше).
Приложению нужно знать лишь название класса и интерфейс, а реализация на усмотрение программиста. Можа я их буду раз в месяц менять (формы в пакете)...   smile  Работоспособность прграммы не должна страдать))))

Конкретно
Код

 MyObject := TFormClass(GetClass('TMyClass')).Create(nil);
 if MyObject.GetInterface(TMyInterface,MyInterface) then
   MyInterface.ShowForm; // вызвали процедуру, т.е. показали форму хранящуюся в пакете

Не я придумал. Перелопатил в инете не мало инфы по пакетам. Это лучший вариант. 
Реализацию делегированием еще не освоил, а абстрактные классы - не есть хорошо.... не зря же лучшие умы придумывали и разрабатывали интерфейсы)))))

если что-то излишне подробно описал - звиняйте) боялся пропустить че-нить важное)
Если Вы тоже используете пакеты, поделитесь опытом, буду рад)

Автор: CodeMonkey 5.12.2008, 10:40
Брррр...
Если вы уж используете интерфейсы - то и передавайте между bpl и exe именно IMyInterface! Зачем вы передаёте класс? Класс - это же реализация. Насколько я понимаю, идеология такая: нужно передавать интерфейс, но не реализацию.

Я, конечно, хз, но сделал бы как-то так:

Пакет:

Unit2 - интерфейс:
Код
unit Unit2;

interface

type
  IMyInterface = interface
    procedure DoIt;
  end;

implementation

end.


Unit3 - реализация:
Код
unit Unit3;

interface

uses
  Unit2, SysUtils, Classes, Forms, Dialogs;

type
  TMyInterface = class(TInterfacedObject, IMyInterface)
    procedure DoIt;
  end;

implementation

{ TMyInterface }

procedure TMyInterface.DoIt;
begin
  ShowMessage('gg!');
end;

end.


Unit4 - получение экземпляра (может быть объединён с Unit2):
Код
unit Unit4;

interface

uses
  Unit2;

function GetMyInterface: IMyInterface;

implementation

uses
  Unit3;

function GetMyInterface: IMyInterface;
begin
  Result := TMyInterface.Create;
end;

end.


Приложение:

Unit1 - использование интерфейса:
Код
unit Unit1;

...

uses
  Unit2, Unit4;

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
var
  Intf: IMyInterface;
begin
  Intf := GetMyInterface;
  Intf.DoIt;
end;

...


Но если вам уж очень сильно охота, то наследуйте свой класс от TPersistent. Почему у вас ограничение в TObject?

P.S. Если бы вы изначально задали вопрос именно вот так вот развёрнуто, то вам бы сразу дали ответ по теме, а не мусолили его несколько дней.

Автор: Avers 5.12.2008, 11:30
Тоже, наверно, вариант (передавать только интерфейс). Надо попробовать.... Пользуюсь наиболее подходящим методом (из всех найденых на просторах интернета), позволяющим связать  Bpl и Приложение.
....

Цитата(CodeMonkey @  5.12.2008,  10:40 Найти цитируемый пост)
наследуйте свой класс от TPersistent. Почему у вас ограничение в TObject?

жесткой привязки нет. 
Такое решение напрашивается само собой. Но было интересно узнать - есть ли другие пути))

Цитата(Avers @  4.12.2008,  12:45 Найти цитируемый пост)
я и подумал, зачем мне чего-то мудрить с другими классами, если достаточно TObject для реализации задуманного

Автор: Avers 8.12.2008, 11:47
Код

unit Unit1;

...

uses
  Unit2, Unit4;


Если использовать в программе Unit4, который в свою оцередь использует Unit2 и Unit3, то смысл наличия пакета теряется (имхо).

Автор: CodeMonkey 8.12.2008, 15:11
Вас смущает необходимость наличия Unit3? Ну так сделайте ссылку косвенно, например:

Код
unit Unit4;

interface

uses
  Unit2;

type
  T = function: IMyInterface;

var
  GetMyInterface: T;

implementation

end.


Код
unit Unit3;

interface

uses
  Unit2, SysUtils, Classes, Forms, Dialogs;

type
  TMyInterface = class(TInterfacedObject, IMyInterface)
    procedure DoIt;
  end;

implementation

uses
  Unit4;

{ TMyInterface }

procedure TMyInterface.DoIt;
begin
  ShowMessage('gg!');
end;

function GetMyInterface: IMyInterface;
begin
  Result := TMyInterface.Create;
end;

initialization
  Unit4.GetMyInterface := Unit3.GetMyInterface;  

end.


Хотя тогда уж проще использовать ручную загрузку пакета:

Unit2 - интерфейс (пакет и exe):
Код
unit Unit2;

interface

type
  IMyInterface = interface
    procedure DoIt;
  end;

  TGetMyIntfProc = function: IMyInterface;

const
  GetMyInterfaceName = 'GetMyInterfaceDefaultImpl';

implementation

end.


Unit3 - реализация (пакет):
Код
unit Unit3;

interface

uses
  Unit2, SysUtils, Classes, Forms, Dialogs;

type
  TMyInterface = class(TInterfacedObject, IMyInterface)
    procedure DoIt;
  end;

implementation

function GetMyInterface: IMyInterface;
begin
  Result := TMyInterface.Create;
end;

exports
  GetMyInterface name GetMyInterfaceName;

{ TMyInterface }

procedure TMyInterface.DoIt;
begin
  ShowMessage('gg!');
end;

end.


Unit1 - использование интерфейса:
Код
unit Unit1;

...

uses
  Unit2;

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
var
  GetMyInterface: TGetMyIntfProc;
  Intf: IMyInterface;
begin
  GetMyInterface := GetProcAddress(LoadPackage('gg.bpl'), GetMyInterfaceName); // или GetModuleHandle вместо LoadPackage
  Intf := GetMyInterface;
  Intf.DoIt;
end;

...


Тока что-то это уже совсем-совсем плагины начинает напоминать.

Автор: Avers 8.12.2008, 22:08
 Вот-вот. В этом вся суть
Цитата(CodeMonkey @  8.12.2008,  15:11 Найти цитируемый пост)
Хотя тогда уж проще использовать ручную загрузку пакета:

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

Автор: Avers 10.12.2008, 13:06
Спасибо) Предолженный вариант с передачей только интерфейса - замечатльно работает.
Даже немного обидно. Когда искал в инете статьи и искходники на эту тему подобного нашлось.... 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)