my $r = IOC::Registry->new('MyApp');
my $c = IOC::Container->new('DBI');
$c->register(IOC::Service::Literal->new('dsn' => 'dbi:mysql:test'));
$c->register(IOC::Service::Literal->new('username' => 'test'));
$c->register(IOC::Service::Literal->new('password' => '****'));
$c->register(IOC::Service::ConstructorInjection->new('connection' => (
'DBI', 'connect' [
IOC::Service::ConstructorInjection->ComponentParameter('dsn'),
IOC::Service::ConstructorInjection->ComponentParameter('username'),
IOC::Service::ConstructorInjection->ComponentParameter('password')
]
)));
$r->registerContainer($c);
# ... then in my app all I have to do is
my $reg = IOC::Registry->instance(); my $db_conn = $reg->locateService('/MyApp/DBI/connection');
Writing the code to configure the services, containers and registry though, can get quite tiring. Fortunately, I really only need to do this once and then just use it, but ideally I would like it to be a little less taxing on the carpal tunnel.
My first idea was to create subclasss of IOC::Container that would take a number of arguments and return a fully formed container. I wrote a basic IOC::Container::DBI which only needed to be passed a $dsn, $username and $password and it would create what I have above. But that idea only works for common things which you do all the time, not for custom stuff.
Then it occurred to me that it would be even nicer to have some kind of very basic configuration syntax/mini-language which would do this. So i searched the Config:: namespace on CPAN and found nothing which seemed to fit the bill.
So before I start really writing a custom parser and such I thought I would get the opinion of others. Here is an example of how the above configuration might look:
MyApp: [ DBI: [ dsn: 'dbi:mysql:test' username: test password: '****' connection: [ DBI connect [ @dsn @username @password ] ] ] ]
This would roughly translate into the following perl data structure, which I would then use to create the actual IOC objects:
{
'MyApp' => {
'DBI' => {
'dsn' => 'dbi:mysql:test',
'username' => 'test',
'password' => '****',
'connection' => [ 'DBI', 'connect', [ 'dsn', 'username', 'password' ]]
}
}
}
So as you can see in some cases, blocks ([]) will become hashes, and in others they will become arrays. The way it knows is that if the first value is a string with a colon at the end (:) it is a hash, otherwise it is an array. The '@' prefix/sigil would indicate that the value is not just a string, but a path or name of a component within the IOC::Container.
I have worked out more complex examples as well, for instance this is how IOC::Service::SetterInjection would be handled:
FileLogger: [ FlieLogger new [ [ set_log_file: @/MyApp/log_file_name ] ]]
this would become the following IOC configuration:
IOC::Service::SetterInjection->new('FileLogger' => ( 'FileLogger', 'new', [ { set_log_file => '/MyApp/log_file_name' } ] )))
I have also devised a way to do the regular IOC::Service object, which use the sub-ref parameter. Here is an example of the DBI configuration above using this:
MyApp: [
DBI: [
dsn: 'dbi:mysql:test'
username: test
password: '****'
connection: <<<
my $c = shift;
return DBI->connect($c->get('dsn'), $c->get('username'), $c->get('password'));
>>>
]
]
It would be like substituting this in the first config example:
$c->register(IOC::Service::->new('connection' => sub {
my $c = shift;
return DBI->connect($c->get('dsn'), $c->get('username'), $c->get('password'));
}));
Obviously the string between '<<<' and '>>>' will get wrapped in 'sub { }' and evaled. I am assuming that this will work since '<<<' and '>>>' are not valid perl identifiers, so I can easily find the end of that string.
As I said, I am still toying around with this. I have created a quick and dirty parser already so I know the syntax is workable for that angle. My question to you all, is;
1) Does this sound like a good idea?
2) Does this syntax look good?
3) Is there any existing Config:: module out there which will do the dirty work for me?
4) Anyone got any better ideas?
Thanks,
Steve
_______________________________________________ sw-design mailing list sw-design@metaperl.com http://metaperl.com/cgi-bin/mailman/listinfo/sw-design