Skip to content

Commit a2dfb42

Browse files
Added dependency injection
1 parent 05a40da commit a2dfb42

File tree

5 files changed

+115
-0
lines changed

5 files changed

+115
-0
lines changed

CodeEdit.xcodeproj/project.pbxproj

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@
5959
2B7AC06B282452FB0082A5B8 /* Media.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2B7AC06A282452FB0082A5B8 /* Media.xcassets */; };
6060
2BE487EF28245162003F3F64 /* FinderSync.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2BE487EE28245162003F3F64 /* FinderSync.swift */; };
6161
2BE487F428245162003F3F64 /* OpenWithCodeEdit.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 2BE487EC28245162003F3F64 /* OpenWithCodeEdit.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
62+
300051672BBD3A5D00A98562 /* ServiceContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 300051662BBD3A5D00A98562 /* ServiceContainer.swift */; };
63+
3000516A2BBD3A8200A98562 /* ServiceType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 300051692BBD3A8200A98562 /* ServiceType.swift */; };
64+
3000516C2BBD3A9500A98562 /* ServiceWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3000516B2BBD3A9500A98562 /* ServiceWrapper.swift */; };
6265
3026F50F2AC006C80061227E /* InspectorAreaViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3026F50E2AC006C80061227E /* InspectorAreaViewModel.swift */; };
6366
30E6D0012A6E505200A58B20 /* NavigatorSidebarViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30E6D0002A6E505200A58B20 /* NavigatorSidebarViewModel.swift */; };
6467
3E0196732A3921AC002648D8 /* codeedit_shell_integration.zsh in Resources */ = {isa = PBXBuildFile; fileRef = 3E0196722A3921AC002648D8 /* codeedit_shell_integration.zsh */; };
@@ -601,6 +604,9 @@
601604
2BE487EC28245162003F3F64 /* OpenWithCodeEdit.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = OpenWithCodeEdit.appex; sourceTree = BUILT_PRODUCTS_DIR; };
602605
2BE487EE28245162003F3F64 /* FinderSync.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FinderSync.swift; sourceTree = "<group>"; };
603606
2BE487F028245162003F3F64 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
607+
300051662BBD3A5D00A98562 /* ServiceContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServiceContainer.swift; sourceTree = "<group>"; };
608+
300051692BBD3A8200A98562 /* ServiceType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServiceType.swift; sourceTree = "<group>"; };
609+
3000516B2BBD3A9500A98562 /* ServiceWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServiceWrapper.swift; sourceTree = "<group>"; };
604610
3026F50E2AC006C80061227E /* InspectorAreaViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InspectorAreaViewModel.swift; sourceTree = "<group>"; };
605611
30E6D0002A6E505200A58B20 /* NavigatorSidebarViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigatorSidebarViewModel.swift; sourceTree = "<group>"; };
606612
3E0196722A3921AC002648D8 /* codeedit_shell_integration.zsh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = codeedit_shell_integration.zsh; sourceTree = "<group>"; };
@@ -1247,6 +1253,16 @@
12471253
path = OpenWithCodeEdit;
12481254
sourceTree = "<group>";
12491255
};
1256+
300051652BBD3A4400A98562 /* DependencyInjection */ = {
1257+
isa = PBXGroup;
1258+
children = (
1259+
300051662BBD3A5D00A98562 /* ServiceContainer.swift */,
1260+
300051692BBD3A8200A98562 /* ServiceType.swift */,
1261+
3000516B2BBD3A9500A98562 /* ServiceWrapper.swift */,
1262+
);
1263+
path = DependencyInjection;
1264+
sourceTree = "<group>";
1265+
};
12501266
3026F50B2AC006A10061227E /* ViewModels */ = {
12511267
isa = PBXGroup;
12521268
children = (
@@ -1354,6 +1370,7 @@
13541370
58798244292E78D80085B254 /* CodeFile */,
13551371
58FD7603291EA1CB0051D6E4 /* Commands */,
13561372
284DC84B2978B5EB00BF2770 /* Contributors */,
1373+
300051652BBD3A4400A98562 /* DependencyInjection */,
13571374
043C321227E31FE8006AE443 /* Documents */,
13581375
6C147C3C29A328020089B630 /* Editor */,
13591376
6C6BD6ED29CD123000235D17 /* Extensions */,
@@ -3201,6 +3218,7 @@
32013218
B65B11012B09D5D4002852CF /* GitClient+Pull.swift in Sources */,
32023219
2072FA13280D74ED00C7F8D4 /* HistoryInspectorModel.swift in Sources */,
32033220
852E62012A5C17E500447138 /* PageAndSettings.swift in Sources */,
3221+
3000516C2BBD3A9500A98562 /* ServiceWrapper.swift in Sources */,
32043222
587B9DA029300ABD00AC7927 /* PanelDivider.swift in Sources */,
32053223
58822534292C280D00E83CDE /* CursorLocation.swift in Sources */,
32063224
201169E52837B40300F92B46 /* SourceControlNavigatorRepositoryView.swift in Sources */,
@@ -3416,6 +3434,7 @@
34163434
587B9E6329301D8F00AC7927 /* GitLabAccount.swift in Sources */,
34173435
6C1CC99B2B1E7CBC0002349B /* FindNavigatorIndexBar.swift in Sources */,
34183436
285FEC7027FE4B9800E57D53 /* ProjectNavigatorTableViewCell.swift in Sources */,
3437+
300051672BBD3A5D00A98562 /* ServiceContainer.swift in Sources */,
34193438
6CB9144B29BEC7F100BC47F2 /* (null) in Sources */,
34203439
587B9E7429301D8F00AC7927 /* URL+URLParameters.swift in Sources */,
34213440
61538B902B111FE800A88846 /* String+AppearancesOfSubstring.swift in Sources */,
@@ -3520,6 +3539,7 @@
35203539
58D01C97293167DC00C5B6B4 /* String+SHA256.swift in Sources */,
35213540
B6EA1FFD29DB792C001BF195 /* ThemeSettingsColorPreview.swift in Sources */,
35223541
2806E904297958B9000040F4 /* ContributorRowView.swift in Sources */,
3542+
3000516A2BBD3A8200A98562 /* ServiceType.swift in Sources */,
35233543
6C578D8C29CD372700DC73B2 /* ExtensionCommands.swift in Sources */,
35243544
B6041F5229D7D6D6000F3454 /* SettingsWindow.swift in Sources */,
35253545
B6EA1FF829DB78DB001BF195 /* ThemeSettingThemeRow.swift in Sources */,

CodeEdit/AppDelegate.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ final class AppDelegate: NSObject, NSApplicationDelegate, ObservableObject {
1616
private var openWindow
1717

1818
func applicationDidFinishLaunching(_ notification: Notification) {
19+
setupServiceContainer()
1920
enableWindowSizeSaveOnQuit()
2021
Settings.shared.preferences.general.appAppearance.applyAppearance()
2122
checkForFilesToOpen()
@@ -231,6 +232,15 @@ final class AppDelegate: NSObject, NSApplicationDelegate, ObservableObject {
231232
}
232233
}
233234

235+
/// Setup all the services into a ServiceContainer for the application to use.
236+
fileprivate func setupServiceContainer() {
237+
// Example for how services will be instantiated
238+
// ServiceContainer.register(
239+
// type: PasteboardService.self,
240+
// PasteboardService()
241+
// )
242+
}
243+
234244
extension AppDelegate {
235245
static let recoverWorkspacesKey = "recover.workspaces"
236246
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
//
2+
// ServiceContainer.swift
3+
// CodeEdit
4+
//
5+
// Created by Abe Malla on 4/3/24.
6+
//
7+
8+
enum ServiceContainer {
9+
private static var factories: [String: () -> Any] = [:]
10+
private static var cache: [String: Any] = [:]
11+
12+
static func register<Service>(type: Service.Type, _ factory: @autoclosure @escaping () -> Service) {
13+
factories[String(describing: type.self)] = factory
14+
}
15+
16+
static func resolve<Service>(_ resolveType: ServiceType = .singleton, _ type: Service.Type) -> Service? {
17+
let serviceName = String(describing: type.self)
18+
19+
switch resolveType {
20+
case .singleton:
21+
if let service = cache[serviceName] as? Service {
22+
return service
23+
} else {
24+
let service = factories[serviceName]?() as? Service
25+
26+
if let service = service {
27+
cache[serviceName] = service
28+
}
29+
30+
return service
31+
}
32+
case .newSingleton:
33+
let service = factories[serviceName]?() as? Service
34+
35+
if let service = service {
36+
cache[serviceName] = service
37+
}
38+
39+
return service
40+
case .new:
41+
return factories[serviceName]?() as? Service
42+
}
43+
}
44+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//
2+
// ServiceType.swift
3+
// CodeEdit
4+
//
5+
// Created by Abe Malla on 4/3/24.
6+
//
7+
8+
enum ServiceType {
9+
/// Returns a new singleton on the first call, then returns a cached one every other time
10+
case singleton
11+
/// Creates a new singleton reference each time and caches it, returning the newer singleton
12+
case newSingleton
13+
/// Creates a new singleton
14+
case new
15+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//
2+
// ServiceWrapper.swift
3+
// CodeEdit
4+
//
5+
// Created by Abe Malla on 4/3/24.
6+
//
7+
8+
@propertyWrapper
9+
struct Service<Service> {
10+
11+
var service: Service
12+
13+
init(_ type: ServiceType = .singleton) {
14+
guard let service = ServiceContainer.resolve(type, Service.self) else {
15+
let serviceName = String(describing: Service.self)
16+
fatalError("No service of type \(serviceName) registered!")
17+
}
18+
19+
self.service = service
20+
}
21+
22+
var wrappedValue: Service {
23+
get { self.service }
24+
mutating set { service = newValue }
25+
}
26+
}

0 commit comments

Comments
 (0)