|
From: Chris W. <ch...@cw...> - 2003-01-13 15:51:48
|
Nick Sutterer wrote:
> hi all!
>
> i'm thinking of providing a "plug-in" mechanism so that programmers can
> extend an existing SPOPS object with additional properties and even new
> functionality (methods).
>
> i use the setup found in the SPOPS/eg dir which is of course chris' idea:
> - have one class per object
> - the class has at least two methods which are
> - _base_config(): returns the SPOPS config hash
> - config_class(): calls SPOPS::Initialize->process() with the config hash
> from _base_config()
>
> my idea is to write a new sub-class of the respective object. the
> constructor of the new object will call the "_base_config" method from its
> parent and extend the returned array as necessary, eg with more "has_a"
> fields.
>
> there are a few problems with this technique:
> if an object has "has_a" properties (which are again classes), the
> config_class() methods of these classes have to be called *before* the
> respective class calls SPOPS::Initialize->process(), because the "has_a"
> classes must be "known" by the SPOPS subsystem (which means, they must
> have been created by SPOPS before).
Fortunately there's a way to do this in SPOPS using
SPOPS::ClassFactory behaviors.
To start with: every SPOPS class goes through a runtime code
generation process that looks like this:
1 2 3
configuration --> Process configuration --> SPOPS class
ClassFactory behaviors allow you to declare steps between 2 and 3
to either modify the configuration before it's processed or to
generate code to go into the generated class.
I'm not sure where you're getting 'has_a' information from, but
what you'd want to do is something like this (untested):
package My::SPOPS::Rules;
use strict;
use SPOPS qw( _w DEBUG );
use SPOPS::ClassFactory qw( OK ERROR DONE );
sub behavior_factory {
my ( $class ) = @_;
return { manipulate_configuration => \&insert_hasa_config };
}
sub insert_hasa_config {
my ( $class ) = @_;
my $CONFIG = $class->CONFIG;
my %hasa_info = get_hasa_information_from_somewhere( ... );
while ( my ( $hasa_class, $hasa_conf ) = each %hasa_info ) {
$CONFIG->{has_a}{ $hasa_class } = $hasa_conf;
}
return ( OK, undef );
}
1;
(where 'get_hasa_information_from_somewhere(...)' is defined by you.)
You'd use this by adding 'My::SPOPS::Rules' to the 'rules_from'
key of your class configuration:
my %config = (
foo => {
class => 'My::Foo',
rules_from => [ 'My::SPOPS::Rules' ],
...
);
You can also generate the methods for 'has_a' if you'd like, but
this is a bit more involved.
For more information, see SPOPS::Manual::CodeGeneration,
SPOPS::ClassFactory and SPOPS::ClassFactory::DefaultBehavior.
Good luck!
Chris
--
Chris Winters (ch...@cw...)
Building enterprise-capable snack solutions since 1988.
|