http://raa.ruby-lang.org/project/mindi/
This version of MinDI adds a new container type, InjectableContainer,
which lets you hook up services via method_missing. See the second
example below. I'd be interested if anyone knows the correct term for
this kind of DI. It's definitely not setter or constructor injection.
(The first example below is constructor injection.) Maybe "fallback
injection", or "duck interface injection" ?
An excerpt from the intro.txt file:
== MinDI
MinDI is Minimalist Dependency Injection for Ruby. It is inspired by
Jamis Buck's Needle (http://needle.rubyforge.org) and Jim Weirich's
article on DI in Ruby
(http://onestepback.org/index.cgi/Tech/Ruby/DependencyInjectionInRuby.rdoc).
MinDI is minimalist in that it attempts to map concepts of DI into basic
ruby
constructs, rather than into a layer of specialized constructs. In
particular, classes and modules function as containers and registries,
and methods and method definitions function as service points and
services. There are some inherent advantages and disadvantages to this
approach, discussed below.
MinDI builds on this minimal DI container by adding the
InjectableContainer concept, which is a kind of DI available only in
dynamic languages: through the magic of <tt>method_missing</tt>, a
service may invoke other services without having explicit setter or
constructor references to those services.
=== Synopsis
<i>Using the BasicContainer module for constructor injection:</i>
require 'mindi'
class SimpleContainer
include MinDI::BasicContainer
greeting { "Hello, world\n" }
point_at { |x,y| [x,y] }
stuff { [greeting, point_at(100,200)] }
end
cont = SimpleContainer.new
p cont.stuff # ==> ["Hello, world\n", [100, 200]]
<i>Using the InjectableContainer module for "dynamic" or "fallback"
injection, using <tt>method_missing</tt>:</i>
require 'mindi'
class Transformer
def transform string
string.gsub(pattern, &replacement)
end
end
class TransformerContainer
include MinDI::InjectableContainer
pattern { /foo/ }
replacement { proc {|match| match.upcase } }
transformer { Transformer.new }
transform { |str| transformer.transform(str) }
end
cont = TransformerContainer.new
s1 = cont.transform("fo foo fee")
s2 = cont.transform("fo foo fee")
p s1 # ==> "fo FOO fee"
p s1.equal?(s2) # ==> true
Note that the Transformer class is written without explicitly linking up
to services (either in initialize or in setters). It just assumes that
the services will be defined in the container.
Note also that the #transform service is a multiton service, and (like
singleton services) it caches its value for each argument.
···
--
vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407