Project Name | Stars | Downloads | Repos Using This | Packages Using This | Most Recent Commit | Total Releases | Latest Release | Open Issues | License | Language |
---|---|---|---|---|---|---|---|---|---|---|
Inversifyjs | 9,728 | 4,740 | 1,436 | 16 days ago | 77 | October 14, 2021 | 266 | mit | TypeScript | |
A powerful and lightweight inversion of control container for JavaScript & Node.js apps powered by TypeScript. | ||||||||||
Swinject | 5,698 | 269 | 10 days ago | 37 | August 03, 2022 | 53 | mit | Swift | ||
Dependency injection framework for Swift with iOS/macOS/Linux | ||||||||||
Loopback Next | 4,458 | 162 | 291 | 6 days ago | 133 | August 25, 2022 | 245 | other | TypeScript | |
LoopBack makes it easy to build modern API applications that require complex integrations. | ||||||||||
Blog.core | 4,243 | 9 days ago | 18 | April 12, 2022 | 4 | apache-2.0 | C# | |||
💖 ASP.NET Core 6.0/7.0 全家桶教程,前后端分离后端接口,vue教程姊妹篇,官方文档: | ||||||||||
Autofac | 4,099 | 10,872 | 3,537 | 13 days ago | 75 | May 25, 2022 | 18 | mit | C# | |
An addictive .NET IoC container | ||||||||||
Tsyringe | 3,889 | 29 | 167 | 16 days ago | 23 | May 27, 2022 | 71 | mit | TypeScript | |
Lightweight dependency injection container for JavaScript/TypeScript | ||||||||||
Typedi | 3,490 | 310 | 409 | 6 days ago | 26 | January 15, 2021 | 37 | mit | TypeScript | |
Simple yet powerful dependency injection tool for JavaScript and TypeScript. | ||||||||||
Awilix | 2,723 | 294 | 195 | 2 months ago | 75 | May 02, 2022 | 4 | mit | TypeScript | |
Extremely powerful Inversion of Control (IoC) container for Node.JS | ||||||||||
Typhoon | 2,715 | 162 | 2 years ago | 137 | July 03, 2020 | 33 | apache-2.0 | Objective-C | ||
Powerful dependency injection for Objective-C ✨✨ (https://PILGRIM.PH is the pure Swift successor to Typhoon!!)✨✨ | ||||||||||
Python Dependency Injector | 2,703 | 5 | 56 | 19 days ago | 287 | March 30, 2022 | 129 | bsd-3-clause | Python | |
Dependency injection framework for Python |
GoLobby Container is a lightweight yet powerful IoC (dependency injection) container for Go projects. It's built neat, easy-to-use, and performance-in-mind to be your ultimate requirement.
Features:
It requires Go v1.11
or newer versions.
To install this package, run the following command in your project directory.
go get github.com/golobby/container/v3
Next, include it in your application:
import "github.com/golobby/container/v3"
GoLobby Container is used to bind abstractions to their implementations. Binding is the process of introducing appropriate concretes (implementations) of abstractions to an IoC container. In this process, you also determine the resolving type, singleton or transient. In singleton bindings, the container provides an instance once and returns it for all the requests. In transient bindings, the container always returns a brand-new instance for each request. After the binding process, you can ask the IoC container to make the appropriate implementation of the abstraction that your code needs. Then your code will depend on abstractions, not implementations!
The following example demonstrates a simple binding and resolving.
// Bind Config interface to JsonConfig struct
err := container.Singleton(func() Config {
return &JsonConfig{...}
})
var c Config
err := container.Resolve(&c)
// `c` will be the instance of JsonConfig
The following snippet expresses singleton binding.
err := container.Singleton(func() Abstraction {
return Implementation
})
// If you might return an error...
err := container.Singleton(func() (Abstraction, error) {
return Implementation, nil
})
It takes a resolver (function) whose return type is the abstraction and the function body returns the concrete (implementation).
The example below shows a singleton binding.
err := container.Singleton(func() Database {
return &MySQL{}
})
The example below shows a transient binding.
err := container.Transient(func() Shape {
return &Rectangle{}
})
You may have different concretes for an abstraction. In this case, you can use named bindings instead of typed bindings. Named bindings take the dependency name into account as well. The rest is similar to typed bindings. The following examples demonstrate some named bindings.
// Singleton
err := container.NamedSingleton("square", func() Shape {
return &Rectangle{}
})
err := container.NamedSingleton("rounded", func() Shape {
return &Circle{}
})
// Transient
err := container.NamedTransient("sql", func() Database {
return &MySQL{}
})
err := container.NamedTransient("noSql", func() Database {
return &MongoDB{}
})
The process of creating concrete (resolving) might face an error. In this case, you can return the error as the second return value like the example below.
err := container.Transient(func() (Shape, error) {
return nil, errors.New("my-app: cannot create a Shape implementation")
})
It could be applied to other binding types.
Container resolves the dependencies with the Resolve()
, Call()
, and Fill()
methods.
The Resolve()
method takes reference of the abstraction type and fills it with the appropriate concrete.
var a Abstraction
err := container.Resolve(&a)
// `a` will be an implementation of the Abstraction
Example of resolving using references:
var m Mailer
err := container.Resolve(&m)
// `m` will be an implementation of the Mailer interface
m.Send("[email protected]", "Hello Milad!")
Example of named-resolving using references:
var s Shape
err := container.NamedResolve(&s, "rounded")
// `s` will be an implementation of the Shape that named rounded
The Call()
method takes a receiver (function) with arguments of abstractions you need.
It calls it with parameters of appropriate concretes.
err := container.Call(func(a Abstraction) {
// `a` will be an implementation of the Abstraction
})
Example of resolving using closures:
err := container.Call(func(db Database) {
// `db` will be an implementation of the Database interface
db.Query("...")
})
You can also resolve multiple abstractions like the following example:
err := container.Call(func(db Database, s Shape) {
db.Query("...")
s.Area()
})
You are able to raise an error in your receiver function, as well.
err := container.Call(func(db Database) error {
return db.Ping()
})
// err could be `db.Ping()` error.
Caution: The Call()
method does not support named bindings.
The Fill()
method takes a struct (pointer) and resolves its fields.
The example below expresses how the Fill()
method works.
type App struct {
mailer Mailer `container:"type"`
sql Database `container:"name"`
noSql Database `container:"name"`
other int
}
myApp := App{}
err := container.Fill(&myApp)
// [Typed Bindings]
// `myApp.mailer` will be an implementation of the Mailer interface
// [Named Bindings]
// `myApp.sql` will be a sql implementation of the Database interface
// `myApp.noSql` will be a noSql implementation of the Database interface
// `myApp.other` will be ignored since it has no `container` tag
You can resolve dependencies at the binding time if you need previous dependencies for the new one.
The following example shows resolving dependencies at binding time.
// Bind Config to JsonConfig
err := container.Singleton(func() Config {
return &JsonConfig{...}
})
// Bind Database to MySQL
err := container.Singleton(func(c Config) Database {
// `c` will be an instance of `JsonConfig`
return &MySQL{
Username: c.Get("DB_USERNAME"),
Password: c.Get("DB_PASSWORD"),
}
})
By default, the Container keeps your bindings in the global instance. Sometimes you may want to create a standalone instance for a part of your application. If so, create a standalone instance like the example below.
c := container.New()
err := c.Singleton(func() Database {
return &MySQL{}
})
err := c.Call(func(db Database) {
db.Query("...")
})
The rest stays the same. The global container is still available.
You might believe that the container shouldn't raise any error and/or you prefer panics. In this case, Must helpers are for you. Must helpers are global methods that panic instead of returning errors.
c := container.New()
// Global instance:
// c := container.Global
container.MustSingleton(c, func() Shape {
return &Circle{a: 13}
})
container.MustCall(c, func(s Shape) {
// ...
})
// Other Must Helpers:
// container.MustSingleton()
// container.MustSingletonLazy()
// container.MustNamedSingleton()
// container.MustNamedSingletonLazy()
// container.MustTransient()
// container.MustTransientLazy()
// container.MustNamedTransient()
// container.MustNamedTransientLazy()
// container.MustCall()
// container.MustResolve()
// container.MustNamedResolve()
// container.MustFill()
Both the singleton and transient binding calls have a lazy version. Lazy versions defer calling the provided resolver function until the first call. For singleton bindings, It calls the resolver function only once and stores the result.
Lazy binding methods:
container.SingletonLazy()
container.NamedSingletonLazy()
container.TransientLazy()
container.NamedTransientLazy()
The package Container inevitably uses reflection for binding and resolving processes. If performance is a concern, try to bind and resolve the dependencies where it runs only once, like the main and init functions.
GoLobby Container is released under the MIT License.