-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
482 additions
and
107 deletions.
There are no files selected for viewing
105 changes: 105 additions & 0 deletions
105
CarbonCore/CarbonCore/CarbonCore.docc/Advanced usage.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
# Advanced usage | ||
|
||
Advanced usage and design of DSL | ||
|
||
## Overview | ||
|
||
### Design of DSL | ||
|
||
DefinitionBuilder is a DSL Syntax used to build ObjectDefinition. | ||
ObjectDefinition is the definition of the object and stores the data needed to resolve the object. | ||
|
||
These data are divided into 4 types: | ||
* Key: The unique identifier of the object definition, used to locate | ||
* Factory: The closure used to create the object and the dependencies that need to be built during creation | ||
* Autowired: Dependencies that need to be built after creation | ||
* Configuration: Other configuration of the object | ||
|
||
DefinitionBuilder has 10 subclasses. Each subclass is used to set a type of ObjectDefinition data. | ||
|
||
Their corresponding relationship is as follows: | ||
* Key: ``KeyDefinitionBuilder``, ``AliasDefinitionBuilder``, ``DynamicAliasDefinitionBuilder`` | ||
* Factory: ``FactoryDefinitionBuilder``, ``DynamicFactoryDefinitionBuilder``, ``DynamicClassDefinitionBuilder`` | ||
* Autowired: ``AutowiredDefinitionBuilder``, ``DynamicAutowiredDefinitionBuilder`` | ||
* Configuration: ``AttributeDefinitionBuilder``, ``ActionDefinitionBuilder`` | ||
|
||
The method of each DefinitionBuilder controls which methods can be used in the next step by controlling the returned DefinitionBuilder type. So you can only complete an ObjectDefinition in a set order. Each DefinitionBuilder controls which settings can be omitted by controlling the inheritance relationship. | ||
|
||
The specifications are as follows, '>' means order, italics means it can be omitted. It doesn't matter if you are confused, the compiler will tell you the correct way. | ||
|
||
* *Key* > *Alias* > Factory > *Autowired* > *Attribute* > *Action* | ||
* Key > *DynamicAlias* > *DynamicFactory* > DynamicClass > *DynamicAutowired* > *Attribute* > *Action* | ||
|
||
### Circular dependency | ||
|
||
During the life cycle of object creation, the creation of dependent objects will be temporarily stored. This design can solve most recursion caused by circular dependencies. | ||
|
||
When there is a circular dependency, it is recommended that at least one object in the circular chain use property or setter injection to build dependencies, this will create dependent objects after the root object is created, using previously created object will break the loop. | ||
|
||
In the following example, both parent and childParent have values and are the same object. | ||
|
||
```swift | ||
let parentBuilder = Definition() | ||
.protocol(ParentProtocol.self) | ||
.object(Parent()) | ||
.property(\.child) | ||
let childBuilder = Definition() | ||
.protocol(ChildProtocol.self) | ||
.object(Child()) | ||
.property(\.parent) | ||
|
||
context.register(builder: parentBuilder) | ||
context.register(builder: childBuilder) | ||
|
||
let parent = context[ParentProtocol.self] as! Parent | ||
let childParent = (parent.child as! Child).parent | ||
``` | ||
The same as: | ||
```swift | ||
let parentBuilder = Definition() | ||
.protocol(ParentProtocol.self) | ||
.object(Parent()) | ||
.property(\.child) | ||
let childBuilder = Definition() | ||
.protocol(ChildProtocol.self) | ||
.constructor(Child.init(parent:)) | ||
``` | ||
|
||
If the constructor is used to build dependencies, this will create dependent objects when the object creation is not completed, which will inevitably cause recursion. | ||
|
||
In the following example, resolving ParentProtocol will trigger the dead lock assertion. | ||
|
||
```swift | ||
let parentBuilder = Definition() | ||
.protocol(ParentProtocol.self) | ||
.constructor(Parent.init(child:)) | ||
|
||
let childBuilder = Definition() | ||
.protocol(ChildProtocol.self) | ||
.constructor(Child.init(parent:)) | ||
|
||
context.register(builder: parentBuilder) | ||
context.register(builder: childBuilder) | ||
``` | ||
|
||
> Tips: If you must use the constructor to build dependencies, at least one object in the circular chain is a singleton, which also avoids recursion. | ||
### Thread safety | ||
|
||
Object resolving is thread-safe, but registration methods are currently not thread-safe, these methods will be marked in the interface comment - “Note: It's not thread-safe, do not use it in a multi-threaded environment.” | ||
|
||
## Topics | ||
|
||
### DSL Syntax | ||
|
||
- ``DefinitionBuilder`` | ||
|
||
- ``GroupDefinitionBuilder`` | ||
|
||
- ``ConfigurationBuilder`` | ||
|
||
- ``Configuration`` | ||
|
||
## See Also | ||
|
||
- <doc:Module-management> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
# Basic usage | ||
|
||
Object registration and resolving. | ||
|
||
## Overview | ||
|
||
* Basic object registration and resolving | ||
```swift | ||
let context = ObjectContext() | ||
context.register(builder: Definition().object(FileViewController())) | ||
context[FileViewController.self] | ||
``` | ||
|
||
* Use configuration batch registration | ||
```swift | ||
class MyConfiguration: ScannableObject, Configuration { | ||
static func definitions() -> Definitions { | ||
Definition() | ||
.object(FilePath()) | ||
Definition() | ||
.constructor(FileModel.init(filePath:)) | ||
} | ||
} | ||
|
||
let context = ObjectContext() | ||
context.register(configuration: MyConfiguration.self) | ||
context[FileModel.self] | ||
``` | ||
|
||
> Note: For convenience, the registration of object definitions and the creation of context that appear in the following will be omitted. All definitions in your project must be registered before they can be resolved. | ||
### Object Scope | ||
|
||
* default: Default object life cycle, alias of prototype | ||
* prototype: Local object life cycle | ||
* singleton: Singleton object life cycle | ||
* weakSingleton: Weak reference singleton object life cycle | ||
|
||
```swift | ||
Definition() | ||
.protocol(FileManagerProtocol.self) | ||
.object(FileManager()) | ||
.scope(.singleton) | ||
``` | ||
|
||
* Multiple object definition methods | ||
```swift | ||
Definition().object(FilePath()) | ||
Definition().constructor(FilePath.init) | ||
Definition().factory { _ in FilePath() } | ||
context[FileModel.self] | ||
``` | ||
|
||
* Define protocol alias for object | ||
```swift | ||
Definition() | ||
.object(FileModel(path: "/") as FileModelProtocol) | ||
context[FileModelProtocol.self] | ||
``` | ||
The same as: | ||
```swift | ||
Definition() | ||
.protocol(FileModelProtocol.self) | ||
.object(FileModel(path: "/")) | ||
``` | ||
|
||
* Define multiple protocol aliases for the object | ||
```swift | ||
Definition() | ||
.protocol(FileManagerProtocol.self) | ||
.alias(ImageManagerProtocol.self) | ||
.alias(DirectoryManagerProtocol.self) | ||
.object(FileManager()) | ||
context[FileManagerProtocol.self] | ||
context[ImageManagerProtocol.self] | ||
context[DirectoryManagerProtocol.self] | ||
``` | ||
The same as: | ||
```swift | ||
Definition() | ||
.protocol(FileManagerProtocol.self) | ||
.alias([ImageManagerProtocol.self, DirectoryManagerProtocol.self]) | ||
.object(FileManager()) | ||
``` | ||
|
||
* Use constructor for dependency injection | ||
```swift | ||
Definition() | ||
.protocol(FileViewControllerProtocol.self) | ||
.constructor(FileViewController.init(fileManager:)) | ||
context[FileViewControllerProtocol.self].fileManager | ||
``` | ||
|
||
* Use property for dependency injection | ||
```swift | ||
Definition() | ||
.protocol(FileViewControllerProtocol.self) | ||
.object(FileViewController()) | ||
.property(\.fileManager) | ||
context[FileViewControllerProtocol.self].fileManager | ||
``` | ||
|
||
* Use setter for dependency injection | ||
```swift | ||
Definition() | ||
.protocol(FileViewControllerProtocol.self) | ||
.object(FileViewController()) | ||
.setter(FileViewController.setFileManager) | ||
context[FileViewControllerProtocol.self].fileManager | ||
``` | ||
|
||
* Use static factory for manual dependency injection | ||
```swift | ||
Definition() | ||
.factory(fileViewController(context:)) | ||
context[FileViewControllerProtocol.self].fileManager | ||
|
||
static func fileViewController(context: ObjectContext) -> FileViewControllerProtocol { | ||
let fileVC = FileViewController() | ||
fileVC.fileManager = context[FileManagerProtocol] | ||
return fileVC | ||
} | ||
``` | ||
The same as: | ||
```swift | ||
Definition() | ||
.factory { context in | ||
let fileVC = FileViewController() | ||
fileVC.fileManager = context[FileManagerProtocol] | ||
return fileVC as FileViewControllerProtocol | ||
} | ||
``` | ||
|
||
* Create objects with external parameters | ||
```swift | ||
Definition() | ||
.factory(fileModel(context:path:name:)) | ||
context[FileModelProtocol.self, "/china/beijing", "family.png"] | ||
|
||
static func fileModel(context: ObjectContext, path: String, name: String) -> FileModelProtocol { | ||
FileModel(path: path, name: name) | ||
} | ||
``` | ||
|
||
## Topics | ||
|
||
### Convenience registration | ||
|
||
- ``ObjectContext/register(protocol:cls:name:)`` | ||
|
||
- ``ObjectContext/register(protocol:object:name:)`` | ||
|
||
### Context | ||
|
||
- ``ObjectContext`` | ||
|
||
- ``ObjectScope`` | ||
|
||
### DSL Syntax | ||
|
||
- ``DefinitionBuilder`` | ||
|
||
- ``Configuration`` | ||
|
||
## See Also | ||
|
||
- <doc:Advanced-usage> | ||
|
||
- <doc:Module-management> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,61 @@ | ||
# ``CarbonCore`` | ||
|
||
<!--@START_MENU_TOKEN@-->Summary<!--@END_MENU_TOKEN@--> | ||
CarbonGraph is a Swift dependency injection / lookup framework for iOS. You can use it to build loose coupling between modules. | ||
|
||
## Overview | ||
|
||
<!--@START_MENU_TOKEN@-->Text<!--@END_MENU_TOKEN@--> | ||
 | ||
|
||
## Topics | ||
* Complete dependency injection capabilities | ||
* Complete Objective-C support | ||
* Convenient object definition DSL | ||
* High-performance thread-safe solution | ||
* Support resolving native Swift types | ||
* Support resolving with external parameters | ||
* Support resolving with circular dependencies | ||
* Automatic scanning of configuration | ||
* Additional module life cycle management capabilities | ||
|
||
### <!--@START_MENU_TOKEN@-->Group<!--@END_MENU_TOKEN@--> | ||
|
||
- <!--@START_MENU_TOKEN@-->``Symbol``<!--@END_MENU_TOKEN@--> | ||
The CarbonGraph project contains 2 frameworks, If only used in Swift, just import CarbonCore, otherwise import both. | ||
|
||
| Framework | Description | | ||
| --- | --- | | ||
| CarbonCore | Focused specifically on core DI implementations | | ||
| CarbonObjC | CarbonCore's ObjC adaptation framework | | ||
|
||
## Quick Start | ||
|
||
* Basic object registration and resolving | ||
```swift | ||
let context = ObjectContext() | ||
let definitionBuilder = Definition("filevc") | ||
.protocol(UIViewController.self) | ||
.object(FileViewController()) | ||
context.register(builder: definitionBuilder) | ||
context[UIViewController.self, name: "filevc"] | ||
``` | ||
|
||
```swift | ||
let context = ObjectContext() | ||
let definitionBuilder = Definition() | ||
.object(FileManager() as FileManagerProtocol) | ||
context.register(builder: definitionBuilder) | ||
context[FileManagerProtocol.self] | ||
``` | ||
|
||
* Use configuration batch registration | ||
```swift | ||
class MyConfiguration: Configuration { | ||
static func definitions(of context: ObjectContext) -> Definitions { | ||
Definition() | ||
.object(FilePath()) | ||
Definition() | ||
.constructor(FileModel.init(filePath:)) | ||
} | ||
} | ||
|
||
let context = ObjectContext() | ||
context.register(configuration: MyConfiguration.self) | ||
context[FileModel.self] | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
# Compatibility | ||
|
||
The Requirements and Compatibility | ||
|
||
## Overview | ||
|
||
### CarbonCore Requirements | ||
|
||
| CarbonCore Stable Version | Required iOS Version | Required Swift Version | | ||
| --- | --- | --- | | ||
| 1.2.2 - 1.3.0 | 9.0 | 5.2 | | ||
|
||
### CarbonObjC Version Compatibility | ||
|
||
| CarbonObjC Version | CarbonCore Compatible Version | | ||
| --- | --- | | ||
| 1.2.2 | 1.2.2 | | ||
| 1.3.0 | 1.3.0 | | ||
|
||
### Build for distribution | ||
|
||
| Xcode Version | Swift Version | MacOS Version | Build for distribution | | ||
| --- | --- | --- | --- | | ||
| 11.4 | 5.2 | Catalina 10.15.7 | passing | | ||
| 12.1 | 5.3 | Catalina 10.15.7 | passing | | ||
| 12.4 | 5.3.2 | Catalina 10.15.7 | passing | | ||
| ~~12.5~~ | ~~5.4~~ | ~~Big Sur 11.6~~ | ~~error~~ | | ||
| ~~12.5.1~~ | ~~5.4.2~~ | ~~Big Sur 11.6~~ | ~~error~~ | | ||
| 13.0 | 5.5 | Big Sur 11.6 | passing | | ||
|
||
|
Oops, something went wrong.