dormky 4 Posted January 20 In Data.DB, the dataset events are defined as TDataSetNotifyEvent = procedure(DataSet: TDataSet) of object; This means that such code as MyTableTest.BeforeDelete := procedure (d: TDataSet) begin LogTableOperation('MyTableTestBeforeDelete'); end; not valid. Is there anyway of casting this ? I'd rather not define a procedure in my data module for every event of every table... Share this post Link to post
David Heffernan 2437 Posted January 20 24 minutes ago, dormky said: Is there anyway of casting this ? No, they are fundamentally different things in terms of implementation. Share this post Link to post
Remy Lebeau 1598 Posted January 21 This is documented behavior: https://docwiki.embarcadero.com/RADStudio/en/Anonymous_Methods_in_Delphi Quote you cannot assign an anonymous method to a regular method pointer. Method references are managed types, but method pointers are unmanaged types. Thus, for type-safety reasons, assigning method references to method pointers is not supported. For instance, events are method pointer-valued properties, so you cannot use an anonymous method for an event. 2 Share this post Link to post
JonRobertson 83 Posted January 21 On 1/20/2025 at 8:19 AM, dormky said: I'd rather not define a procedure in my data module for every event of every table... If several tables will use events with identical functionality, such as logging, you can have a single event assigned to multiple tables: procedure TForm1.AllTablesBeforeDelete(DataSet: TDataSet); begin LogTableOperation(DataSet.Name + 'BeforeDelete'); end; MyTable1Test.BeforeDelete := AllTablesBeforeDelete; MyTable2Test.BeforeDelete := AllTablesBeforeDelete; MyTable3Test.BeforeDelete := AllTablesBeforeDelete; Or assign the event handler to each table using the object inspector. Share this post Link to post
dormky 4 Posted January 22 18 hours ago, JonRobertson said: If several tables will use events with identical functionality, such as logging, you can have a single event assigned to multiple tables: procedure TForm1.AllTablesBeforeDelete(DataSet: TDataSet); begin LogTableOperation(DataSet.Name + 'BeforeDelete'); end; MyTable1Test.BeforeDelete := AllTablesBeforeDelete; MyTable2Test.BeforeDelete := AllTablesBeforeDelete; MyTable3Test.BeforeDelete := AllTablesBeforeDelete; Or assign the event handler to each table using the object inspector. That's what I ended up with yes Share this post Link to post
Softacom | Company 10 Posted February 13 You can't just convert it, but you can make same behaviour type TDataSetAnonimouseEvent = reference to procedure(DataSet: TDataSet); TForm3 = class(TForm) FDQuery1: TFDQuery; bntAddNewEvent: TButton; procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure bntAddNewEventClick(Sender: TObject); private { Private declarations } FEventLinks : TDictionary<TComponent, TDataSetAnonimouseEvent>; public { Public declarations } procedure AllTablesBeforeDelete(DataSet: TDataSet); end; var Form3: TForm3; implementation {$R *.dfm} procedure TForm3.AllTablesBeforeDelete(DataSet: TDataSet); begin //check if we have anonymous event for this component if FEventLinks.ContainsKey(DataSet) then begin //call anonymous event FEventLinks[DataSet](DataSet); end; end; procedure TForm3.bntAddNewEventClick(Sender: TObject); begin //link anonymous event to specific component FEventLinks.Add(FDQuery1, procedure(DataSet: TDataSet) begin ShowMessage('Anonimouse event!'); end ); end; procedure TForm3.FormCreate(Sender: TObject); begin FEventLinks := TDictionary<TComponent, TDataSetAnonimouseEvent>.Create; FDQuery1.BeforeDelete := AllTablesBeforeDelete; end; procedure TForm3.FormDestroy(Sender: TObject); begin FreeAndNil(FEventLinks); end; 1 Share this post Link to post
HolgerX 7 Posted February 14 Hmm.. or you make it with a simple helper: type TMakeObjectFunc = class public class procedure Log(d: TDataSet); end; { TMakeObjectFunc } class procedure TMakeObjectFunc.Log(d: TDataSet); begin LogTableOperation('MyTableTestBeforeDel?ete'); end; procedure TForm1.FormCreate(Sender: TObject); begin MyTableTest.BeforeDelete := TMakeObjectFunc.Log; end; Share this post Link to post
yonojoy 3 Posted February 18 Or you could use a wrapper (as demonstrated for TNotifyEvent in https://stackoverflow.com/questions/11491593/tproctobject-to-tnotifyevent): MyTableTest.BeforeDelete := AnonProcToDataSetNotifyEvent(MyTableTest, procedure (D: TDataSet) begin LogTableOperation('MyTableTestBeforeDelete'); end); 1 Share this post Link to post
pmcgee 27 Posted May 10 On 2/18/2025 at 4:01 PM, yonojoy said: Or you could use a wrapper (as demonstrated for TNotifyEvent in https://stackoverflow.com/questions/11491593/tproctobject-to-tnotifyevent): Just following links from this nice link ... Barry Kelly in 2010 : http://blog.barrkel.com/2010/01/using-anonymous-methods-in-method.html Share this post Link to post
David Heffernan 2437 Posted May 11 Is there any known use case other than the one demonstrated by FreeAndNil, namely to allow modification of a const param? Share this post Link to post
Uwe Raabe 2147 Posted May 11 1 hour ago, David Heffernan said: Is there any known use case other than the one demonstrated by FreeAndNil, namely to allow modification of a const param? Wrong thread? What does [ref] attribute actually dows 1 Share this post Link to post