请稍侯

一个支持多实例注册的dicont

22 May 2023

一个支持多实例注册的DIContainer

class DIContainer {
    private var registry: [String: Any] = [:]
    func register<T>(_ type: T.Type, name: String? = nil, factory: @escaping () -> T) {
        let key = "\(type)\(name ?? "")"
        registry[key] = factory
    }
    func resolve<T>(_ type: T.Type, name: String? = nil) -> T? {
        let key = "\(type)\(name ?? "")"
        return (registry[key] as? () -> T)?()
    }
}

使用

protocol MyProtocol {
    func doSomething()
}
class MyClass1: MyProtocol {
    func doSomething() {
        print("MyClass1 did something")
    }
}
class MyClass2: MyProtocol {
    func doSomething() {
        print("MyClass2 did something")
    }
}

// 注册并使用
let container = DIContainer()
container.register(MyProtocol.self, name: "instance1") { MyClass1() }
container.register(MyProtocol.self, name: "instance2") { MyClass2() }

let instance1 = container.resolve(MyProtocol.self, name: "instance1")
instance1?.doSomething() // Output: "MyClass1 did something"
let instance2 = container.resolve(MyProtocol.self, name: "instance2")
instance2?.doSomething() // Output: "MyClass2 did something"

用swift写下个DIContainer, 支持类似java中的注解注册,并支持对不同的实现指定不同name.
ChatGPT 回答:
当然,我可以帮你编写一个支持类似Java中的注解注册的DI容器,并且支持为不同的实现指定不同的名称。在Swift中,我们可以使用属性包装器和反射来实现这个功能。

首先,我们需要定义一个DIContainer类,它将负责注册和解析依赖项。我们可以使用一个字典来存储注册的依赖项,其中键是依赖项的名称,值是依赖项的类型。

class DIContainer {
    private var dependencies: [String: Any] = [:]
    
    func register<T>(_ type: T.Type, name: String? = nil) {
        let key = name ?? String(describing: T.self)
        dependencies[key] = type
    }
    
    func resolve<T>(_ type: T.Type, name: String? = nil) -> T? {
        let key = name ?? String(describing: T.self)
        return dependencies[key] as? T
    }
}

接下来,我们可以定义一个属性包装器@Inject,它可以用于将依赖项注入到类的属性中。我们可以使用反射来获取属性的类型,并使用DIContainer来解析相应的依赖项。

@propertyWrapper
struct Inject<T> {
    private let name: String?
    
    init(name: String? = nil) {
        self.name = name
    }
    
    var wrappedValue: T? {
        get {
            return DIContainer.shared.resolve(T.self, name: name)
        }
    }
}

现在,我们可以使用@Inject属性包装器来注入依赖项。例如,假设我们有一个UserService类,它依赖于UserRepository接口。

protocol UserRepository {
    func getUser() -> String
}

class UserRepositoryImpl: UserRepository {
    func getUser() -> String {
        return "John Doe"
    }
}

class UserService {
    @Inject<UserRepository> var userRepository: UserRepository?
    
    func printUserName() {
        if let user = userRepository?.getUser() {
            print("User: \(user)")
        }
    }
}

现在,我们可以在DIContainer中注册依赖项,并使用UserService类来解析和使用它们。

let container = DIContainer()
container.register(UserRepositoryImpl.self)
container.register(UserRepository.self, name: "mock") // 注册不同的实现并指定名称

let userService = UserService()
userService.printUserName() // 输出: User: John Doe

// 使用不同的实现
container.register(MockUserRepository.self, name: "mock")
userService.printUserName() // 输出: User: Mock User

这就是一个简单的Swift DI容器的实现,它支持类似Java中的注解注册,并且可以为不同的实现指定不同的名称。当然,这只是一个基本的示例,你可以根据自己的需求进行扩展和改进。希望对你有帮助!