Project Name | Stars | Downloads | Repos Using This | Packages Using This | Most Recent Commit | Total Releases | Latest Release | Open Issues | License | Language |
---|---|---|---|---|---|---|---|---|---|---|
Awilix | 3,000 | 294 | 306 | 25 days ago | 77 | April 04, 2023 | mit | TypeScript | ||
Extremely powerful Inversion of Control (IoC) container for Node.JS | ||||||||||
Dryioc | 909 | 122 | 129 | 4 days ago | 434 | April 22, 2022 | 40 | mit | C# | |
DryIoc is fast, small, full-featured IoC Container for .NET | ||||||||||
Jab | 796 | 10 months ago | 11 | mit | C# | |||||
C# Source Generator based dependency injection container implementation. | ||||||||||
Stronginject | 662 | 1 | a year ago | 296 | May 24, 2022 | 17 | mit | C# | ||
compile time dependency injection for .NET | ||||||||||
Swinjectstoryboard | 252 | 83 | a month ago | 15 | September 05, 2021 | 26 | mit | Swift | ||
Swinject extension for automatic dependency injection via Storyboard | ||||||||||
Swinjectautoregistration | 217 | 18 | 5 months ago | 9 | October 03, 2021 | 3 | mit | Swift | ||
Swinject extension to automatically register your services | ||||||||||
Autofac.annotation | 200 | 1 | 2 | 20 days ago | 6 | January 28, 2020 | mit | C# | ||
DI容器,依赖注入,AOP,动态代理等用注解来load autofac 摆脱代码或者xml配置和java的spring的注解注入一样的体验 | ||||||||||
Stashbox | 127 | 18 | 21 | 18 days ago | 345 | March 29, 2023 | 2 | mit | C# | |
A lightweight, fast, and portable dependency injection framework for .NET-based solutions. | ||||||||||
Autofac.extras.quartz | 116 | 25 | 18 | 6 months ago | 181 | March 27, 2023 | 4 | mit | C# | |
Autofac integration for Quartz.Net | ||||||||||
Kickstart | 41 | 11 | a month ago | 72 | August 20, 2022 | 8 | mit | C# | ||
Application initialization helper |
SwinjectAutoregistration is an extension of Swinject that allows to automatically register your services and greatly reduce the amount of boilerplate code.
Swinject is available through Carthage, CocoaPods or Swift Package Manager.
To install Swinject with Carthage, add the following line to your Cartfile
.
github "Swinject/Swinject" "2.8.3"
github "Swinject/SwinjectAutoregistration" "2.8.3"
Then run carthage update --use-xcframeworks --no-use-binaries
command or just carthage update --use-xcframeworks
. For details of the installation and usage of Carthage, visit its project page.
To install Swinject with CocoaPods, add the following lines to your Podfile
.
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '9.0' # or platform :osx, '10.10' if your target is OS X.
use_frameworks!
pod 'Swinject', '2.8.3'
pod 'SwinjectAutoregistration', '2.8.3'
Then run pod install
command. For details of the installation and usage of CocoaPods, visit its official website.
in Package.swift
add the following:
dependencies: [
.package(url: "https://github.com/Swinject/SwinjectAutoregistration.git", from: "2.8.3")
],
targets: [
.target(
name: "MyProject",
dependencies: [..., "SwinjectAutoregistration"]
)
...
]
Here is a simple example to auto-register a pet owner
let container = Container()
container.register(Animal.self) { _ in Cat(name: "Mimi") } // Regular register method
container.autoregister(Person.self, initializer: PetOwner.init) // Autoregistration
where PetOwner looks like this:
class PetOwner: Person {
let pet: Animal
init(pet: Animal) {
self.pet = pet
}
}
The autoregister
function is given the PetOwner
initializer init(pet:Animal)
. From its signature Swinject knows that it needs a dependency Animal
and resolves it from the container. Nothing else is needed.
Autoregistration becomes especially useful when used to register services with many dependencies. Compare autoregistration code:
container.autoregister(MyService.self, initializer: MyService.init)
with equivalent code in pure Swinject:
container.register(MyService.self) { r in
MyService(dependencyA: r.resolve(DependencyA.self)!, dependencyB: r.resolve(DependencyB.self)!, dependencyC: r.resolve(DependencyC.self)!, dependencyD: r.resolve(DependencyD.self)!)
}
Another advantage is that if you add more dependencies during the development the registration code doesn't have to be rewritten.
Service can be also given name - same as with the regular register method.
container.autoregister(Person.self, name: "johnny", initializer: PetOwner.init)
You can also use auto-registration for services with dynamic arguments. Pet owner whose name needs to be passed as argument is defined like this:
class PetOwner: Person {
let name: String
let pet: Animal
init(name: String, pet: Animal) {
self.name = name
self.pet = pet
}
}
And registered like this
container.autoregister(Person.self, argument: String.self, initializer: PetOwner.init)
Swinject will register Person
with the argument of type String
. When container.resolve(Person.self, argument: "Michael")
is called Swinject won't try to resolve String
as dependency but instead pass "Michael" as the name.
To also pass pet as argument you can call
container.autoregister(Person.self, arguments: String.self, Animal.self, initializer: PetOwner.init)
//or
container.autoregister(Person.self, arguments: Animal.self, String.self, initializer: PetOwner.init)
The order of the arguments listed is interchangeable. The auto-registration can't be used with more arguments and/or dependencies of the same type.
Wondering how does that work? Generics are heavily leveraged for the auto-registration. For registering service with two dependencies something similar to a following function is used:
public func autoregister<Service, A, B>(_ service: Service.Type, initializer: (A, B) -> Service) -> ServiceEntry<Service> {
return self.register(service.self, factory: { r in
return initializer(r.resolve(A.self)!, r.resolve(B.self)!)
} as (ResolverType) -> Service)
}
The initializer is a function like any other. By passing it as a parameter its dependencies can be inferred as (A, B)
and automatically resolved. These functions are generated for up to 20 dependencies. Checkout the code for more info.
This extension also aims to reduce the amount of boilerplate while improving readability of the registration code. For that reason the operator ~>
is introduced.
Petowner(pet: r~>)
// equivalent to
Petowner(pet: r.resolve(Animal.self)!)
The dependency is again inferred from the type in the initializer. To specify a concrete class you can use:
Petowner(pet: r ~> Cat.self)
To use a named service:
Petowner(pet: r ~> (Cat.self, name: "mimi"))
or to pass argument/s:
Petowner(pet: r ~> (Cat.self, argument: "Mimi"))
Petowner(pet: r ~> (Cat.self, arguments: ("Mimi", UIColor.black)))
When a service has multiple initializers, swift compiler can't be sure which should be used and you will get a ambigious use of init(x: y: z:)
. This can also happen if the service is extending another class that have initializer with the same number of arguments.
The solution is to specify the initializer like this:
container.autoregister(Person.self, initializer: PetOwner.init(name:pet:))
Auto-registration can't be used with named dependencies in their initializers. There is no way to get a name of dependency from the initializer. For example, following code can't be auto-registered:
container.register(Animal.self, name: "mimi") { _ in Cat(name: "Mimi") }
container.register(Animal.self, name: "charles") { _ in Cat(name: "Charles") }
container.register(Person.self) {
PetOwner(pet: r.resolve(Animal.self, name: "mimi")
}
Since Swift 5.3 the compiler behaves differently when infering initializers in structs that have variables with a default value:
struct Cat {
let height: Int = 50
}
Compiler will generate two init functions:
Cat.init
and Cat.init(height:)
Since the Swift 5.3 the following registration
container.autoregister(Animal.self, initializer: Cat.init)
will try to use the Cat.init(height:)
which will then fail with Unresolved service: Int Initializer: (Int) -> Animal
Solution is to make the compiler use the init without a parameter
container.autoregister(Animal.self, initializer: Cat.init as () -> Cat)
Our release procedure is described as Makefile. Run make help
coomand for more info.
SwinjectAutoregistration generics is inspired by:
MIT license. See the LICENSE file for details.