Brian Candler
10/7/2004 12:41:00 PM
On Thu, Oct 07, 2004 at 08:41:04PM +0900, Jim Weirich wrote:
> One of the variations I discussed with Jamis included the possibility of
> layering DI containers with namespaces. If I understand the concept
> correctly, you configure the base system in a root namespace and then
> layer the variations in namespaces on top of the root. If a service
> isn't located in the specific namespace for the (lets say) Fast CGI
> version, then it uses the services configured in the root. This would
> reduced the duplication in the system.
>
> Another approach is to use a single DI container, but configure it with
> in different methods. One method could populate the static portion of
> the application, and then different methods could populate it according
> to whether it was a Fast CGI configuration or a webrick configuration.
Or maybe it could be as simple as allowing registrations to be overridden;
have a version of #register which does not check for duplicates.
def reregister(name, &block) # or have parameter override=false ?
@services[name] = Service.new(block, self)
end
def unregister(name)
@services.delete(name)
end
and in the application:
require 'myapp/di'
di = Myapp.dependencies
di.reregister(:logger) { |c| ...something different... } # override
di.app.run
It doesn't work for all cases - e.g. where you want to change logging so
that one component gets a different logger. In that particular example, you
could rebuild the dependency information to allow for it:
container.register(:default_logger) { |c| Logger.new(c.logfilename) }
container.register(:eh_logger) { |c| c.default_logger }
container.register(:db_logger) { |c| c.default_logger }
container.register(:error_handler) { |c| ... errh.logger = c.eh_logger ... }
But I wonder if the DI framework could handle it more intelligently,
allowing you to register a different Proc depending on the type of object
being created.
container.register(:logger) { |c| Logger.new("test1") }
container.register(:logger,:error_handler) { |c| Logger.new("test2") }
The second line is "when creating a :logger for an :error_handler, do this".
The first is "when creating a :logger at any other time, do that". Just a
thought; it breaks the idea that c.logger always gives an instance of the
same object though.
Cheers,
Brian.