插件

🔌 即插即用

插件是一个 Swift SPM 项目,它提供了一种灵活且模块化的方法,通过使用插件来增强对象的功能。通过遵循 Plugin 协议,可以创建自定义插件并将其添加到遵循 Pluginable 协议的对象,而无需修改其原始实现。这使开发人员能够以即插即用的方式将自定义行为添加到他们的对象中,从而可以轻松地维护和扩展代码。

用法

创建插件

要创建插件,请创建一个遵循 Plugin 协议的结构体或类,并实现其要求。

这是一个简单的插件示例,它向 URLRequest 对象添加一个 auth 标头

struct AuthPlugin: Plugin {
    var keyPath: WritableKeyPath<PluginURLRequest, URLRequest>

    func handle(value: Void, output: inout URLRequest) async throws {
        output.allHTTPHeaderFields = ["auth": "token"]
    }
}

使对象可插件化

要将插件与对象一起使用,请使其遵循 Pluginable 协议。 这是一个 PluginURLRequest 类的示例,可以向其添加插件

class PluginURLRequest: Pluginable {
    var plugins: [any Plugin] = []

    var request: URLRequest

    init(url: URL) {
        self.request = URLRequest(url: url)
    }
}

注册和处理插件

可以使用 register(plugin: any Plugin) 方法将插件注册到 Pluginable 对象。 注册后,可以在对象上调用 handle(value: Any) 方法,以将注册的插件应用于它。

let urlRequest = PluginURLRequest(url: URL(string: "https://example.com")!)

urlRequest.register(plugin: AuthPlugin(keyPath: \.request))

try await urlRequest.handle()
print(urlRequest.request.allHTTPHeaderFields) // ["auth": "token"]

其他功能

您还可以访问任何插件的 inputTypeoutputType 属性,并获取插件及其 inputTypeoutputType 属性的列表。

let authPlugin = AuthPlugin(keyPath: \.request)
print(authPlugin.inputType) // Void
print(authPlugin.outputType) // URLRequest

let pluginTypes = urlRequest.pluginTypes
print(pluginTypes) // [(input: Void, output: URLRequest)]

使用插件的项目