I think it would be interesting to extend the Events-Sample, how to use anonymous methods
dummy.OnSetName += method(s: SimpleClassWithEvents; var aNewName: string)
begin
MessageBox.Show('Anonymous method: '+aNewName);
end;
var ev : OnSetNameDelegate := method(s: SimpleClassWithEvents; var aNewName: string)
begin
MessageBox.Show('Anonymous method with var: '+ aNewName);
end;
dummy.OnSetName += ev;
I’ve been trying to learn Oxygene for a while now (got the trial version at moment) and as I come from a pure Delphi background it’s been an uphill struggle. One of the things I got stuck on was events and I still do not really understand them that much, they are so different than Delphi’s way of doing things.
Any extra samples to assist in this would be beneficial to others I believe
You can use events in the same (or similar) manner as in Delphi, it’s not necessary to use the event reserved word and += if you have a problem with that:
type
SomeEvent = public delegate;
SomeEventWithSender = public delegate(aSender : SomeEventClass);
SomeEventClass = public class
private
method TriggerEvents;
public
//No need to use FOnEvent1 and FOnEvent2 as in Delphi
property OnEvent1 : SomeEvent;
property OnEvent2 : SomeEventWithSender;
end;
SomeClass = public class
public
constructor(anEventClass : SomeEventClass);
end;
implementation
method SomeEventClass.TriggerEvents;
begin
if assigned(self.OnEvent1) then
self.OnEvent1();
if assigned(self.OnEvent2) then
self.OnEvent2(self);
end;
constructor SomeClass(anEventClass : SomeEventClass);
begin
inherited constructor;
//You can also use regular methods instead of anonymous methods
anEventClass.OnEvent1 :=
method
begin
end;
anEventClass.OnEvent2 :=
method(aSender : SomeEventClass)
begin
end;
end;
Select the code you want to format and click </> button on the toolbar.
About delegates - the way I suggested it will only make it possible to have one event handler per event. AFAIK using event reserved word and += assignment makes it possible to have multiple handlers per event. But so far I never had the need to use it that way.
Yea, it is very rare that I need need multi-cast events, so it is nice to know that I can use the normal Delphi route for standard events and then when / if I need multi-cast events then I can use the event keyword and the += to add more
Sorry for late reply but been trying to get this solved.
How do I do the above as part of an object instead of a anonymous method ? Everytime I try it says that the method requires 0 parameters. I’ve tried defining the method under the implementation (like in Delphi) but then it says Globals are not switched on
Sounds like a bug in the compiler. I almost exclusively use anonymous methods for quite some time, but I’ll try this in a few hours when I’m back from a trip. If it doesn’t work I’ll send a bug report to RO.
Anonymous methods, I’ve found, are brilliant for small snippets of code. For example updating a user interface, switching on things etc. Not so good when the method requires doing a lot (as in a lot of code) because it then starts to look convoluated IMHO.
At moment I am just using them for updating so it’s not so much a headache, but that could change. Would definately appreciate a second view on this
How do I do the above as part of an object instead of a anonymous method ? Everytime I try it says that the method requires 0 parameters. I’ve tried defining the method under the implementation (like in Delphi) but then it says Globals are not switched on
Could you provide a testcase or code snippet you are using?
This is NOT the best example, but I just whipped it up while waiting for some Windows Updates on my work box. At least it shows how to declare a named method on an object that can be notified when an event occurs:
namespace WPFApplication12;
interface
type
MyDelegate = public delegate (Sender: Object; Args: EventArgs);
MyObject = public class
public
method MyMethod( sender : Object; Args : EventArgs );
end;
Window1 = public partial class(System.Windows.Window)
private
method Button_Click(sender: System.Object; e: System.Windows.RoutedEventArgs);
method UnHook_Click(sender: System.Object; e: System.Windows.RoutedEventArgs);
x : MyObject;
public
constructor;
event MyEvent : MyDelegate;
end;
implementation
uses
System.Windows;
method MyObject.MyMethod(sender: Object; Args: EventArgs);
begin
MessageBox.Show( 'hello' );
end;
constructor Window1;
begin
InitializeComponent();
x := new MyObject;
MyEvent += x.MyMethod;
end;
method Window1.Button_Click(sender: System.Object; e: System.Windows.RoutedEventArgs);
begin
if assigned( MyEvent ) then MyEvent( self, nil );
end;
method Window1.UnHook_Click(sender: System.Object; e: System.Windows.RoutedEventArgs);
begin
MyEvent -= x.MyMethod;
end;
end.
Clicking on the button that triggers the Button_Click method call then causes the MyObject instance to say ‘hello’.
After clicking on the button that triggers the UnHook_Click method, MyObject is no longer listening and won’t say ‘hello’ again.
I added this unhook (to my original post) because without undoing event listeners, it is my understanding that you can get into memory leaks. Because that MyObject instance x will continue to take memory even if it is set to nil. Because it would still be listening for the event, the garbage collector won’t free it.
So for events that you listen for once, be sure to unhook the event so objects can be freed.