首页 > 解决方案 > 在 Swift 中,如何实现一个通用系统,通过为不同的键路径注册处理器来处理类型?

问题描述

我想实现一个系统,允许我通过为不同的关键路径注册处理器来一般地处理类型。

系统的一个特征应该是composition,因此每个处理器都应该扩展一个通用的通用协议Processor

使用示例:

struct Language {
    var name = "Swift"
    var version = 5.3
}

var processor = TypeProcessor<Language>()
processor.add(procesor: VersionProcessor(), keypath: \.version)
processor.add(procesor: NameProcessor(), keypath: \.name)

var input = Language()
processor.process(value: input)

// Languge version:     5.3
// Languge name:        Swift

标签: swiftgenericsswift-keypath

解决方案


您可以使用“处理器”的继承,而不是尝试擦除属性类型,其中子类是根对象和属性类型的泛型,并且具有属性键路径。

protocol Processor {
    associatedtype T
    func process(value: T)
}

class AnyProcessor<Value>: Processor {
    func process(value: Value) {
    }
}

final class KeyPathProcessor<Root, P: Processor>: AnyProcessor<Root> {
    typealias Value = P.T

    let keyPath: KeyPath<Root, Value>
    let processor: P

    init(keyPath: KeyPath<Root, Value>, processor: P) {
        self.keyPath = keyPath
        self.processor = processor
    }

    override func process(value: Root) {
        processor.process(value: value[keyPath: keyPath])
    }
}

struct ObjectProcessor<T>: Processor {
    var processors = [AnyKeyPath: AnyProcessor<T>]()

    mutating func add<P: Processor, V>(processor: P, keypath: KeyPath<T, V>) where P.T == V {
        self.processors[keypath] = KeyPathProcessor(keyPath: keypath, processor: processor)
    }

    func process(value: T) {
        for (_, processor) in processors {
            processor.process(value: value)
        }
    }
}

推荐阅读