Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2004.05.30;
Скачать: [xml.tar.bz2];

Вниз

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;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.46 MB
Время: 0.032 c
3-1083336426
TankMan
2004-04-30 18:47
2004.05.30
Посоветуйте компонент...


4-1082023475
esVer
2004-04-15 14:04
2004.05.30
выделенный текст в чужом окне


14-1084001250
infom
2004-05-08 11:27
2004.05.30
Про шахматы


1-1084446108
Lexa_1
2004-05-13 15:01
2004.05.30
MouseToCell в TdxDBGrid - как реализовать?


14-1083873348
SeriousSam
2004-05-06 23:55
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
Английский Французский Немецкий Итальянский Португальский Русский Испанский