Skip to content

Commit

Permalink
Dependency injection v1.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
yoyofx committed Jul 13, 2021
1 parent faa7a49 commit 86d3531
Showing 1 changed file with 54 additions and 31 deletions.
85 changes: 54 additions & 31 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,31 @@
# Dependency injection
Dependency injection for Go programming language.

Dependency injection is one form of the broader technique of inversion of control. It is used to increase modularity of the program and make it extensible.

## Examples
```go
type A struct {
Name string
}

func NewA() *A {
r := rand.New(rand.NewSource(time.Now().UnixNano()))
name := "A-" + strconv.Itoa(r.Int())
return &A{Name: ls}
}

services := NewServiceCollection()
services.AddSingleton(NewA)
//serviceCollection.AddSingletonByImplementsAndName("redis-master", NewRedis, new(abstractions.IDataSource))
//serviceCollection.AddTransientByImplements(NewRedisClient, new(redis.IClient))
//serviceCollection.AddTransientByImplements(NewRedisHealthIndicator, new(health.Indicator))
serviceProvider := services.Build()

var env *A
_ = serviceProvider.GetService(&env) // used
```

## How will dependency injection help me?

Dependency injection is one form of the broader technique of inversion
Expand Down Expand Up @@ -26,18 +54,9 @@ extensible.
## Installing

```shell
go get -u github.com/defval/inject/v2
go get -u github.com/yoyofxteam/[email protected]
```

This library follows [SemVer](http://semver.org/) strictly.

## Tutorial

Let's learn to use Inject by example. We will code a simple application
that processes HTTP requests.

The full tutorial code is available [here](./_tutorial/main.go)

### Providing

To start, we will need to create two fundamental types: `http.Server`
Expand Down Expand Up @@ -67,16 +86,20 @@ func NewServeMux() *http.ServeMux {
Now let's teach a container to build these types.
```go
container := inject.New(
import (
di "github.com/yoyofxteam/dependencyinjection"
)
container := di.New(
// provide http server
inject.Provide(NewServer),
di.Provide(NewServer),
// provide http serve mux
inject.Provide(NewServeMux)
di.Provide(NewServeMux)
)
```
The function `inject.New()` parse our constructors, compile dependency
graph and return `*inject.Container` type for interaction. Container
The function `di.New()` parse our constructors, compile dependency
graph and return `*di.Container` type for interaction. Container
panics if it could not compile.

> I think that panic at the initialization of the application and not in
Expand Down Expand Up @@ -143,7 +166,7 @@ func NewServer(handler http.Handler) *http.Server {
```

For a container to know that as an implementation of `http.Handler` is
necessary to use, we use the option `inject.As()`. The arguments of this
necessary to use, we use the option `di.As()`. The arguments of this
option must be a pointer(s) to an interface like `new(Endpoint)`.

> This syntax may seem strange, but I have not found a better way to
Expand Down Expand Up @@ -232,11 +255,11 @@ provide option.

```go
container := inject.New(
inject.Provide(NewServer), // provide http server
inject.Provide(NewServeMux), // provide http serve mux
di.Provide(NewServer), // provide http server
di.Provide(NewServeMux), // provide http serve mux
// endpoints
inject.Provide(NewOrderController, inject.As(new(Controller))), // provide order controller
inject.Provide(NewUserController, inject.As(new(Controller))), // provide user controller
di.Provide(NewOrderController, di.As(new(Controller))), // provide order controller
di.Provide(NewUserController, di.As(new(Controller))), // provide user controller
)
```

Expand Down Expand Up @@ -276,22 +299,22 @@ type SlaveDatabase struct {
}
```

Second way is a using named definitions with `inject.WithName()` provide
Second way is a using named definitions with `di.WithName()` provide
option:

```go
// provide master database
inject.Provide(NewMasterDatabase, inject.WithName("master"))
di.Provide(NewMasterDatabase, di.WithName("master"))
// provide slave database
inject.Provide(NewSlaveDatabase, inject.WithName("slave"))
di.Provide(NewSlaveDatabase, di.WithName("slave"))
```

If you need to extract it from container use `inject.Name()` extract
If you need to extract it from container use `di.Name()` extract
option.

```go
var db *Database
container.Extract(&db, inject.Name("master"))
container.Extract(&db, di.Name("master"))
```

If you need to provide named definition in other constructor use
Expand Down Expand Up @@ -353,7 +376,7 @@ that transforms to `di.ParameterBag` type.

```go
// Provide server with parameter bag
inject.Provide(NewServer, inject.ParameterBag{
di.Provide(NewServer, di.ParameterBag{
"addr": ":8080",
})

Expand All @@ -369,10 +392,10 @@ func NewServer(pb di.ParameterBag) *http.Server {
### Prototypes

If you want to create a new instance on each extraction use
`inject.Prototype()` provide option.
`di.Prototype()` provide option.

```go
inject.Provide(NewRequestContext, inject.Prototype())
di.Provide(NewRequestContext, di.Prototype())
```

> todo: real use case
Expand Down Expand Up @@ -401,9 +424,9 @@ After `container.Cleanup()` call, it iterate over instances and call
cleanup function if it exists.

```go
container := inject.New(
container := di.New(
// ...
inject.Provide(NewFile),
di.Provide(NewFile),
)

// do something
Expand All @@ -419,7 +442,7 @@ Dependency graph may be presented via
representation:

```go
var graph *di.Graph
var graph *di.di.Graph
if err = container.Extract(&graph); err != nil {
// handle err
}
Expand Down

0 comments on commit 86d3531

Please sign in to comment.