Last active
December 15, 2015 22:09
-
-
Save andypike/5330927 to your computer and use it in GitHub Desktop.
My first experiment with a simple IoC container in Ruby. To run this sample do this: $ ruby ioc.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# defining various components of the system | |
# notice the classes know nothing about the container | |
# as they require the dependencies to operate, they should be passed into the constructor | |
class Nails | |
def to_s | |
"nails" | |
end | |
end | |
class Glue | |
def to_s | |
"glue" | |
end | |
end | |
class PowerSaw | |
def initialize(power_source) | |
@power_source = power_source | |
end | |
def to_s | |
"#{@power_source} power saw" | |
end | |
end | |
class HandSaw | |
def to_s | |
"hand saw" | |
end | |
end | |
class Electricity | |
def to_s | |
"electrical" | |
end | |
end | |
class Carpenter | |
def initialize(tool, fixings) | |
@tool = tool | |
@fixings = fixings | |
end | |
def build_something | |
puts "Building something in wood with #{@fixings} and #{@tool}" | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Container | |
attr_reader :registry | |
def self.create_container | |
@container = self.new | |
yield @container | |
end | |
def self.resolve(key) | |
klass = @container.registry[key] | |
constructor_params = klass.instance_method(:initialize).parameters | |
required_dependancies = constructor_params.select{|p| p.first == :req} | |
.map{|p| resolve(p.last)} | |
klass.new(*required_dependancies) # add some options for lifecycle etc | |
end | |
def initialize | |
@registry = {} | |
end | |
def register(key, klass) | |
@registry[key] = klass | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require './container' | |
require './classes' | |
# register the components of the system with the container | |
# as we can't use types to inject the correct dependency we rely on the convention | |
# of the constructor parameter names matching the keys registered | |
# this is where you swap implementations to change behaviour without touching your classes | |
Container.create_container do |c| | |
c.register :craftsman, Carpenter | |
c.register :tool, PowerSaw | |
c.register :fixings, Nails | |
c.register :power_source, Electricity | |
end | |
# resolve the root object, all dependencies will be instantiated and injected | |
craftsman = Container.resolve(:craftsman) | |
craftsman.build_something | |
# $ ruby ioc.rb | |
# => Building something in wood with nails and electrical power saw |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment