From: Eivind Eklund Date: 2004-10-12T00:09:06+09:00 Subject: Re: DI service change notifications (Syringe) On Mon, 11 Oct 2004 09:12:47 +0900, Jamis Buck wrote: > I guess what I'm feeling is that there is no general way to know, > definitively, all of the dependencies of a service, especially in a > dynamic language like Ruby. Without putting restrictions on when and how > services are defined (like Copland does), I'm not sure how to come up > with a general solution to this. I get a feeling you're overengineering here. Doesn't something like the following work? class Registry def initialize @registry = Hash.new @active_dependency_registrations = [] @dependencies = Hash.new end # This is done by method_missing in Syringe def get(symbol) register_dependency(symbol) retval = nil begin start_dependency(symbol) @registery[symbol].call finally end_dependency(symbol) end end def register(symbol, &block) @registery[symbol] = block end def start_dependency(symbol) if (@active_dependencies.include? symbol) raise "Circular dependency" else @active_dependencies.each do |dependent_symbol| @dependencies[dependent_symbol] ||= [] @dependencies[dependent_symbol] |= [symbol] end @active_dependencies |= [symbol] end end def end_dependency(symbol) @active_dependencies -= [symbol] end end It builds a dependency tree only inside the present registry. It only count the directly called methods from call/yield, but that should be OK for most cases. And this is just pseudo-code - it's not the way I'd write it for production (I'd use Set and Hash.default, and handle threads, and ...) Eivind.