vladislav-yashin / crystal-di

Lightweight DI Container for Crystal

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Tagged services

Blacksmoke16 opened this issue · comments

Hey, first off, this is my new favorite shard. I had a feature request that would make it even better; the ability to tag services. For example

class FeedPartner
  include DI::Taggable

  getter id : String
  getter name : String

  def initialize(@id : String, @name : String); end
end

module Container
  include DI::ContainerMixin

  register FeedPartner, FeedPartner.new("GOOGLE", "Google"), tag: "feed_partner"
  register FeedPartner, FeedPartner.new("FACEBOOK", "Facebook"), tag: "feed_partner"
end

partners = Container.tagged "feed_partner" # => # => [#<FeedPartner:0x7f0f7891bd00 @id="GOOGLE", @name="Google">, #<FeedPartner:0x7f0f7891bcc0 @id="FACEBOOK", @name="Google">]

My current idea to implement this would be to define a module like DI::Taggable that can be included into types that the user wants to be able to be tagged.

Then the ContainerMixin could define a hash like @@services = Hash(String, Array(DI::Taggable)).new, where upon adding a resolve method, add that value to hash for the given tag.

\{% if type.resolve < DI::Taggable %}
  @@services[\{{tag}}] = Array(DI::Taggable).new unless @@services.has_key? \{{tag}}
  @@services[\{{tag}}] << \{{value}}.as(\{{type}})
\{% end %}

Finally, implement a method to get services based on tag:

def self.tagged(tag : String)
  @@services[tag]? || [] of DI::Taggable
end

I currently have this working on my fork, however I wanted to get your thoughts before making a PR.