https://github.com/sleipnir/injectx
Elixir dependency injection
https://github.com/sleipnir/injectx
Last synced: 4 months ago
JSON representation
Elixir dependency injection
- Host: GitHub
- URL: https://github.com/sleipnir/injectx
- Owner: sleipnir
- License: apache-2.0
- Created: 2021-07-24T17:49:43.000Z (almost 5 years ago)
- Default Branch: main
- Last Pushed: 2021-08-04T14:06:53.000Z (almost 5 years ago)
- Last Synced: 2025-10-20T08:54:34.715Z (8 months ago)
- Language: Elixir
- Size: 50.8 KB
- Stars: 5
- Watchers: 1
- Forks: 2
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Injectx
**Context Dependency Injection for Elixir**
## Installation
If [available in Hex](https://hex.pm/docs/publish), the package can be installed
by adding `injectx` to your list of dependencies in `mix.exs`:
```elixir
def deps do
[
{:injectx, "~> 0.1.0"}
]
end
```
`Injectx` module is a entrypoint to CDI.
## Usage:
Define your Behavior module:
```elixir
defmodule FooBehavior do
@callback greetings(String.t()) :: String.t()
end
```
Implement it:
```elixir
defmodule FooImpl do
@behavior FooBehavior
@impl true
def greetings(_name) do
"Hello from FooImpl"
end
end
```
Initialize Injectx Context on Application bootstrap:
```elixir
defmodule App do
use Application
alias Injectx.Context
@impl true
def start(_type, _args) do
context = %Context{
bindings: [
%Context.Binding{
behavior: FooBehavior,
definitions: [
%Context.BindingDefinition{module: FooImpl, default: true}
]
}
]
}
Context.from(context)
children = [
...
]
opts = [strategy: :one_for_one, name: App.Supervisor]
Supervisor.start_link(children, opts)
end
end
```
### Use your behavior via Implementation resolved in runtime (using inject macro with same sintaxe of alias):
```elixir
defmodule Bar do
use Injectx
inject TestBehaviour
def greetings(name), do: TestBehaviour.greetings(name)
end
```
### Or you can inject all implementations at once (using inject_all function):
```elixir
defmodule Caller do
use Injectx
# resolve all injection bindings for certain behavior
@all inject_all(TestBehaviour)
....
def call(),
do: Enum.each(@all, fn impl -> impl.greetings("Teddy") end)
end
```
## Dispatching
Injectx also provides the ability to dynamically dispatch your implementations.
For this it is only necessary to use the dispatcher function. Sync and Async are possible options:
```elixir
defmodule SomeBehaviour do
@callback test(integer()) :: {:ok, integer()}
end
defmodule SomeImpl1 do
@behaviour SomeBehaviour
def test(1), do: {:ok, 1}
end
defmodule SomeImpl2 do
@behaviour SomeBehaviour
def test(1), do: {:ok, 2}
end
... bootstrap
@impl true
def start(_type, _args) do
context = %Context{
bindings: [
%Context.Binding{
behavior: SomeBehaviour,
definitions: [
%Context.BindingDefinition{module: SomeImpl1, default: true},
%Context.BindingDefinition{module: SomeImpl2}
]
}
]
}
Context.from(context)
....
end
...write some client module...
defmodule SomeClientModule do
use Injectx
def call(arg), do: dispatching(TestBehaviour, :test, [arg], async: true)
end
...then call it `iex -S mix`
iex(1)> SomeClientModule.call(1)
[{:ok, InjectxTest.TestImpl2, {:ok, 2}}, {:ok, InjectxTest.TestImpl1, {:ok, 1}}]
```