XServiceLocator 1.0.0

XServiceLocator 1.0.0

Ghulam Nasir维护。



  • 作者
  • Stefan Kofler, Mathias Quintero 和 Ghulam Nasir

XServiceLocator

"渴望恰当的依赖注入?"

Build Status CocoaPods Compatible Carthage Compatible Platform License: MIT

XServiceLocator 是一个轻量级的 Swift 库/框架,用于动态地为对象提供它们需要的依赖。该库基于服务定位模式。其想法是,对象从某个存储中获取它们的依赖。XServiceLocator 允许您在 iOS 应用程序中无缝地使用依赖注入,而无需任何后台魔法。

🔩组件

📦容器

存储创建注册类型实例的配置

🛠️解析器

通过创建类的实例来解析特定类型的实际实现,使用容器的配置

🏭服务工厂

一个通用的工厂解决方案,用于创建泛型类型的实例

🏃‍♀️开始使用

🚶‍♀️基本步骤

  1. 使用任何两种 register 方法中的一种,将所有类型注册到容器中。
let container = Container()
            .register(Int.self, instance: 10)
            .register(Double.self) { _ in 20 }
  1. 无论何时需要该类型的实例,都可以使用 Resolver 的任何两种 resolve 方法之一来访问它。首先从 Container 获取Resolver,然后使用它来解决依赖。
  let resolver = container.resolver

  let intValue = try! resolver.resolve(Int.self)
  let doubleValue: Double = try! resolver.resolve()

🎲自定义对象

您还可以为协议注册自定义类型或实例,例如

// Setting up

protocol Shape {
    var name: String { get }
}

class Circle: Shape {
    let name = "Circle"
    let radius: Double

    init(radius: Double) {
        self.radius = radius
    }

}

class Rectangle: Shape {
    let name = "Rectangle"
    let width: Double
    let height: Double

    init(width: Double, height: Double) {
        self.width = width
        self.height = height
    }
}

struct Drawing {
    let shape: Shape
}

// Registering all the dependencies

let container = Container()
    .register(Shape.self, instance: Circle(radius: 10))
    .register(Circle.self) { _ in Circle(radius: 20) }
    .register(Rectangle.self, instance: Rectangle(width: 30, height: 15))
    .register(Drawing.self) { _ in
        let shape = Rectangle(width: 10, height: 5)
        return Drawing(shape: shape)
    }


// Resolving the dependencies

let resolver = container.resolver

let rectangle = try! resolver.resolve(Rectangle.self)
let shape = try! resolver.resolve(Shape.self)
let circle: Circle = try! resolver.resolve()
let drawing: Drawing = try! resolver.resolve()

// Accessing values

print(rectangle.name) // Rectangle
print(shape.name) // Circle
print(circle.name) // Circle
print(drawing.shape.name) // Rectangle

print("\(rectangle.width), \(rectangle.height)") // 30.0, 15.0
print((shape as! Circle).radius) // 10.0
print(circle.radius) // 20.0

🎩使用已注册的实例进行后续注册

// Registering all the dependencies
let container = Container()
    .register(Double.self, instance: 30)
    .register(Rectangle.self, instance: Rectangle(width: 10, height: 20))
    .register(Circle.self) { resolver in Circle(radius: try! resolver.resolve()) }


// Resolving the dependencies

let resolver = container.resolver

let circle: Circle = try! resolver.resolve()


// Accessing values

circle.radius // 30.0

👶使用(子)依赖解析器

一个容器可以有另一个解析器作为依赖,如果主解析器(容器)未能解决依赖,则可以使用该解析器进行解决。

// Registering all the dependencies

let dependency = Container()
            .register(Double.self, instance: 100)
            .register(Shape.self, instance: Rectangle(width: 10, height: 20))

let container = Container(dependency: dependency)
    .register(Rectangle.self, instance: Rectangle(width: 15, height: 7.5))


// Resolving the dependencies

let resolver = container.resolver

let shapeRectangle = try! resolver.resolve(Shape.self) as! Rectangle
let rectangle: Rectangle = try! resolver.resolve()
let doubleValue: Double = try! resolver.resolve()


// Accessing values

print("\(shapeRectangle.width), \(shapeRectangle.height)") // 10.0, 20.0
print("\(rectangle.width), \(rectangle.height)") // 15.0, 7.5
print(doubleValue) // 100

💪解析器数组

解析器数组也充当解析器。只要数组中的任何元素能够成功解决,就返回对象。

// Registering all the dependencies

let container = Container()
    .register(Int.self, instance: 10)
    .register(Double.self, instance: 20)

let container1 = Container()
    .register(Float.self, instance: 30)
    .register(Double.self, instance: 50)

let arrayOfResolvers: Resolver = [
    container,
    container1,
]


// Resolving the dependencies
let intValue = try! arrayOfResolvers.resolve(Int.self)   // 10
let floatValue = try! arrayOfResolvers.resolve(Float.self)   // 30.0
let doubleValue = try! arrayOfResolvers.resolve(Double.self)   // 20.0

‍🤷‍♂️ 为什么使用服务定位模式呢?

  1. 类/对象之间的松散耦合
  2. 提供了更好的可测试性
  3. 提供可扩展性。新的实例可以轻松注册,实现可以在不进行大量更改的情况下切换。

为什么是 XServiceLocator?

  1. 即插即用。集成库后即可开始使用。
  2. 支持解包器数组。可以组合使用多个解包器来解析类型。
  3. 支持注册和解析任何类型。
  4. 由一群真正关心社区及其解决方案质量的开发者开发和维护。
  5. 所有内容仅使用 Swift 构建。没有 Objective-C 遗留代码。

🛠安装

CocoaPods

要使用 CocoaPods 将 XServiceLocator 集成到 Xcode 项目中,请将以下内容添加到您的 Podfile

pod 'XServiceLocator', '~> 1.0'

Carthage

要使用 Carthage 将 XServiceLocator 集成到您 Xcode 项目中,请将以下内容添加到您的 Cartfile

github "quickbirdstudios/XServiceLocator" ~> 1.0

然后运行 carthage update

如果您这是第一次在项目中使用 Carthage,您需要按照以下步骤进行一些操作,具体说明请参考 Carthage

Swift 包管理器

有关如何在您的应用程序中采用 Swift 包的更多信息,请参阅 此 WWDC 演示

https://github.com/quickbirdstudios/XServiceLocator.git 指定为 XServiceLocator 包链接。

手动

如果您不希望使用任何依赖管理器,可以通过下载源代码并将文件放在您的项目目录中来手动将 XServiceLocator 集成到您的 iOS 项目中。

👤作者

本框架是用以下方式创建的❤️QuickBird Studios 提供。

❤️贡献

如果您需要帮助、发现了一个错误或想要讨论功能请求,请打开一个 issue。

如果您想要对 XServiceLocator 进行更改,请打开一个 PR。

📃许可协议

XServiceLocator 采用 MIT 许可协议发布。有关更多信息,请参阅 License.md