Tuesday, January 17, 2006

Custom EventArgs

I don't know if there is a name for this pattern or not but I have found that it is quite helpfull. When creating custom events it should only have two parameters. One being the object that raised the event and the other should be an object containing data.

I like examples so lets start with these two classes:

public class MyApp

private withEvents eventClass as MyEventRaiser

private sub DoTask()
eventClass.DoTask()
end sub

private sub eventClass_MyEvent(arg1 as string, arg2 as integer, arg3 as bool) handles eventClass.MyEvent

messagebox.show(arg1)
end sub

end class


public class MyEventRaiser

public event MyEvent(arg1 as string, arg2 as integer, arg3 as bool)

public sub DoTask()
RaiseEvent MyEvent("test", 32, true)
end sub

end class


This is fairly cut and dry. When a call to MyEventRaiser.DoTask() is run an event is raised. In this case it is handled by MyClass.eventClass_MyEvent().

The problem with this setup comes to making changes. In every project there is change. We might run into a case where we need to return another parameter when the event gets raised. We could add it on to the event declaration, the RaiseEvent statement, and every place it is handled.

If the event is handled in 50 places we have to make 50 changes. Even though it might be that only one of those handlers actually cares about the new parameter.

To mitigate this issue we create a class that inherits from eventArgs:


public class MyEventArgs
inherits EventArgs

private _arg1 as string
private _arg2 as integer
private _arg3 as boolean

public property Arg1 as string
get
return _arg1
end get
set (value as string)
_arg1 = value
end set
end property

public property Arg2 as integer
get
return _arg2
end get
set (value as integer)
_arg2 = value
end set
end property

public property Arg3 as boolean
get
return _arg3
end get
set (value as boolean)
_arg3 = value
end set
end property

public sub new (arg1 as string, arg2 as integer, arg3 as bool)
_arg1 = arg1
_arg2 = arg2
_arg3 = arg3
end sub
end class

So now we have an object that encapsulates all of the data for our event. We then change our
class that declares the event like so:

public class MyEventRaiser

public event MyEvent(sender as object, e as MyEventArgs)

public sub DoTask()
RaiseEvent MyEvent(me, New MyEventArgs("test", 32, true))
end sub
end class

Starting to look familiar? This is what microsoft did for all of its built in events. The sender is always the object that raised the event. This allows the objects that receive the event access to the object that created it.

Now the only thing left is to change the signature of the methods that handle the method.

public class MyApp

private withEvents eventClass as MyEventRaiser

private sub DoTask()
eventClass.DoTask()
end sub

private sub eventClass_MyEvent(sender as object, e as MyEventArgs) handles eventClass.MyEvent

messagebox.show(e.arg1)
end sub

end class

From now on if we need to add a new parameter we simply add it onto the MyEventArgs class.
By doing this we dont need to change 50 method signatures to accept a new parameter that the method never uses.

Happy Eventing!

0 Comments:

Post a Comment

<< Home