use Attribute::Handlers; use Carp; sub private :ATTR(CODE) { my ($package, $symbol, $referent, $attr, $data, $phase) = @_; my $name = *{$symbol}{NAME}; *{$symbol} = sub { croak "Function $name is declared private in $package" if caller ne $package; $referent->(@_) } } #### package EventHandlers; our %EventHandlers; use Attribute::Handlers; use Carp; sub Event :ATTR(CODE) { my ($package, $symbol, $referent, $attr, $data, $phase) = @_; my $name = *{$symbol}{NAME}; $EventHandlers{$name} = 1; } #### package Annotations; my %Annotations; sub Annotate { my ($sub, %annotations) = @_; bless $sub, Annotations; my $h = $Annotations{$sub} ||= {}; @$h{keys %annotations} = values %annotations; } sub annotation { my ($this, $name) = @_; $Annotations{$this}{$name} } #### package Events; use Annotations; use Attribute::Handlers; sub Event :ATTR(CODE) { my ($package, $symbol, $referent, $attr, $data, $phase) = @_; Annotations::Annotate($referent, eventhandler => 1); } #### if (my $event = MyEvents->can($CGI->param('event'))) { die unless $event->annotation('eventhandler'); MyEvents->$event(); } #### $event->{eventhandler} #### annotation($event, 'eventhandler')