Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.05.30;
Скачать: CL | DM;

Вниз

procedure of class?   Найти похожие ветки 

 
Sandman25   (2004-05-20 10:38) [0]

Доброе время суток.

Подскажите, пожалуйста, как можно заменить объявление
Type
 TEntityProcedure = procedure (...) of object
чтобы использовать не обычные методы, а "классовые"
class procedure (...)

EntityClassFor(CashData).CallProcAndKeepContext(EntityProcedureFor(CashData), ...)

EntityClassFor возвращает TEntityClass = class of TEntity
EntityProcedureFor возвращает TEntityProcedure
Внутри CallProcAndKeepContext происходит использование "классовых" методов для сохранения/восстановления контекста и между ними вызывается процедура, передаваемая параметром.
Спасибо.


 
Sandman25+1   (2004-05-20 10:44) [1]

Только что проверил в тестовом приложении... Вроде бы никакой разницы нет. Вопрос снимается.
Хотя в реальном приложении access violation происходит именно при вызове метода, переданного параметром и параметр вроде правильный. Буду разбираться.


 
Тимохов ©   (2004-05-20 10:45) [2]

вообще говоря, это прекрасно работает.
в чем проблема?

type
  TCls = class
     class procedure a;
  end;
 TProc = procedure of object;

class
procedure TCls.a;
begin
  showmessage("a");
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  kProc: TProc;
begin
  kProc := TCls.a;
  kProc(); // display "a"
end;


 
Sandman25+1   (2004-05-20 11:10) [3]

Проблема действительно есть. Что-то я неправильно делаю, видимо.

type
 TCashData = (cdMotiveType
 //, ...
 );

 TEntityRecord = record
   EntityClass: TEntityClass;
   EntityProcedure: TEntityProcedure;
 end;

const
 EntityArr: array[TCashData] of TEntityRecord =
(
//    cdMotiveType,
   (EntityClass: TFormularEntity; EntityProcedure: TFormularEntity.Filter)
//, ...
)

function EntityClassFor(CashData: TCashData): TEntityClass;
begin
 Result := EntityArr[CashData].EntityClass;
end;

function EntityProcedureFor(CashData: TCashData): TEntityProcedure;
begin
 Result := EntityArr[CashData].EntityProcedure;
end;

class procedure TEntity.CallProcAndKeepContext(
 EntityProcedure: TEntityProcedure;
 FormatDataAdapter: TFormatDataAdapter);
var
 OldFilterArr: array of String;
 Index: Integer;
begin
 SetLength(OldFilterArr, GetDataSetCount);
 for Index := Low(OldFilterArr) to High(OldFilterArr) do
   OldFilterArr[Index] := TDataSetAdapter.GetOldFilterAndDisableControls(GetDataSet(FormatDataAdapter, Index));
 try
   EntityProcedure(FormatDataAdapter);
 finally
   for Index := Low(OldFilterArr) to High(OldFilterArr) do
     TDataSetAdapter.SetOldFilterAndEnableControls(GetDataSet(FormatDataAdapter, Index), OldFilterArr[Index]);
 end;
end;

Так вот при вызове
   EntityClassFor(CashData).CallProcAndKeepContext(EntityProcedureFor(CashData), FormatDataAdapter);

Я попадаю в TFormularEntity.CallProcAndKeepContext, как и ожидается.
Но в Watch я вижу:
EntityArr[cdmotivetype],r: (EntityClass:TEntityClass($1BB10F0); EntityProcedure:$1BB10A4)
@entityprocedure: $1BB10F0
@tformularentity.filter: $1BB1B74
@tentity.filter: $1BB1B74

Получается, что параметр EntityProcedure указывает не на Tformularentity.filter, а на Tformularentity. Соответственно при вызове
   EntityProcedure(FormatDataAdapter) я получаю Access Violation, даже не заходя в TformularEntity.Filter.
Сообщение Write of address 01BB10B4.

Может, нужно инициализировать массив только в run-time?


 
Sandman25+1   (2004-05-20 11:18) [4]

Проблема похоже есть, причем в моем коде.
type
 TCashData = (cdMotiveType {, ...});

type
 TEntityRecord = record
   EntityClass: TEntityClass;
   EntityProcedure: TEntityProcedure;
 end;

const
 EntityArr: array[TCashData] of TEntityRecord =
   (
// формуляр
//    cdMotiveType,
   (EntityClass: TFormularEntity; EntityProcedure: TFormularEntity.Filter) {,...}
   );

function EntityClassFor(CashData: TCashData): TEntityClass;
begin
 Result := EntityArr[CashData].EntityClass;
end;

function EntityProcedureFor(CashData: TCashData): TEntityProcedure;
begin
 Result := EntityArr[CashData].EntityProcedure;
end;

class procedure TEntity.CallProcAndKeepContext(
 EntityProcedure: TEntityProcedure;
 FormatDataAdapter: TFormatDataAdapter);
var
 OldFilterArr: array of String;
 Index: Integer;
begin
 SetLength(OldFilterArr, GetDataSetCount);
 for Index := Low(OldFilterArr) to High(OldFilterArr) do
   OldFilterArr[Index] := TDataSetAdapter.GetOldFilterAndDisableControls(GetDataSet(FormatDataAdapter, Index));
 try
   EntityProcedure(FormatDataAdapter);
 finally
   for Index := Low(OldFilterArr) to High(OldFilterArr) do
     TDataSetAdapter.SetOldFilterAndEnableControls(GetDataSet(FormatDataAdapter, Index), OldFilterArr[Index]);
 end;
end;

Так вот при вызове
  EntityClassFor(cdMotiveType).CallProcAndKeepContext(EntityProcedureFor(cdMotiveType),
я попадаю, как и ожидается в TformularEntity.CallProcAndKeepContext, но в Watch вижу странные вещи:

entityarr[cdmotivetype],r: (EntityClass:TEntityClass($1BB10F0); EntityProcedure:$1BB10A4)
@entityprocedure: $1BB10F0
@tformularentity.filter: $1BB1B74

То есть локальный параметр EntityProcedure <> entityarr[cdmotivetype].EntityProcedure
И потом получаю AV: write of address 01BB10B4

Может, нужно явно инициализировать массив, а не использовать const?


 
Sandman25+1   (2004-05-20 11:27) [5]

Все, решил :) Сделал инициализацию массива в initialization-секции и проблема исчезла. Const массив почему-то "дурковал" :(



Страницы: 1 вся ветка

Текущий архив: 2004.05.30;
Скачать: CL | DM;

Наверх




Память: 0.48 MB
Время: 0.029 c
3-1083576827
Andreas
2004-05-03 13:33
2004.05.30
Как скопировать схему БД


3-1083711368
Dark Man
2004-05-05 02:56
2004.05.30
Работа с SQL Server 2000 из под Delphi 5


8-1080052987
Pa5ha
2004-03-23 17:43
2004.05.30
Сохранение изображения на холсте в Direct3D


8-1079985708
Cosmit
2004-03-22 23:01
2004.05.30
Delphi и Flash.


3-1084188084
Help_me
2004-05-10 15:21
2004.05.30
как обработать ошибку при отвалившемся коннекте? IB6+IBX