I have a couple of protocols describing a storage provider:
protocol StorageProvider {
associatedtype PathType: StoragePath
var root: PathType { get }
func readFile(atPath path: PathType) -> String
}
protocol StoragePath {
func read() -> String
}
enum StorageType {
case local
case remote
// ...
}
with 2 concrete implementations:
struct LocalStoragePath: StoragePath {
func read() -> String {
return "local"
}
}
struct LocalStorageProvider: StorageProvider {
typealias PathType = LocalStoragePath
var root: LocalStoragePath {
return LocalStoragePath()
}
func readFile(atPath path: LocalStoragePath) -> String {
return path.read()
}
}
struct RemoteStoragePath: StoragePath {
func read() -> String {
return "remote"
}
}
struct RemoteStorageProvider: StorageProvider {
typealias PathType = RemoteStoragePath
var root: RemoteStoragePath {
RemoteStoragePath()
}
func readFile(atPath path: RemoteStoragePath) -> String {
return path.read()
}
}
and a class tying everthing together:
class ContentProvider {
let provider: Any
init(type: StorageType) {
switch type {
case .local:
self.provider = LocalStorageProvider()
case .remote:
self.provider = RemoteStorageProvider()
}
}
func read(path: String) -> String {
if let p = self.provider as? LocalStorageProvider {
return p.readFile(atPath: p.root)
}
if let p = self.provider as? RemoteStorageProvider {
return p.readFile(atPath: p.root)
}
abort()
}
}
However, I am not happy that I have to use type Any for the provider property. I read up on documentation and ended up with a type erased generic storage provider:
class GenericStorageProvider<T: StoragePath>: StorageProvider {
var root: T {
return self._root
}
typealias PathType = T
private let _readFile: (T) -> String
private let _root: T
init<U: StorageProvider>(_ provider: U) where U.PathType == T {
self._readFile = provider.readFile
self._root = provider.root
}
func readFile(atPath path: T) -> String {
return self._readFile(path)
}
}
but that also doesn't work because the provider property in ContentProvider cannot be a GenericStorageProvider, it has to be GenericStorageProvider<T>.
Is there any other way that I am not aware of or does this simply not work as I intended? Besides the initializer in ContentProvider everything is under my control.
Any help is much appreciated