Главная страница
    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.46 MB
Время: 0.039 c
11-1073934915
Maxim Pushkar
2004-01-12 22:15
2004.05.30
Не работает Font.Color для RichEdit?


3-1084420699
Fanta
2004-05-13 07:58
2004.05.30
ADO Access поля типа OLE-объект


14-1084450666
RealRascal
2004-05-13 16:17
2004.05.30
Загадка.


6-1081404340
Сергей Ю.
2004-04-08 10:05
2004.05.30
Размер траффика


1-1084695704
temp
2004-05-16 12:21
2004.05.30
Как создать файл в памяти, т.е. не сохраняя его на диск? Например





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский