Search code examples
swiftdependency-injectionswinject

Swinject: Resolving using a list of metatypes


I'm trying to create a function to return an array of metatypes, which I can then use to resolve instances from a Swinject Resolver. Here's my code:

protocol Task: class { }

func getTypes() -> [Task.Type] {
    return [ConcreteTaskA.self, ConcreteTaskB.self]
}

var concreteTasks = [Task]()
for type in getTypes() {
    // Use a Swinject Container to resolve the metatype.
    let task = container.resolver.resolve(type)! // Error here: Cannot invoke 'resolve' with an argument list of type '(Task.Type)'
    concreteTasks.append(task)
}

I'm not sure how to solve this. Do I need to use generics somehow with the getTypes() method? Do I need to call some equivalent of type.self when resolving?

My requirements are that I can define a list of metatypes ([ConcreteTaskA.self, ConcreteTaskB.self]) to be resolved by a resolver.


Solution

  • So it turns out the issue may lie with using a protocol. I can get the following to work...

    for type in getTypes() {
        // Use a Swinject Container to resolve the metatype.
        if let aType = type as? ConcreteTaskA.Type {
            let task = container.resolver.resolve(aType)!
            concreteTasks.append(task)
        }
    }
    

    ...but obviously it would be nice to not need to check for every type first.

    If we change the protocol to a base class, however, everything works as expected:

    class Task { }
    class ConcreteTaskA: Task { }
    class ConcreteTaskB: Task { }
    
    func getTypes() -> [Task.Type] {
        return [ConcreteTaskA.self, ConcreteTaskB.self]
    }
    
    var concreteTasks = [Task]()
    for type in getTypes() {
        // Use a Swinject Container to resolve the metatype.
        let task = container.resolver.resolve(type)!
        concreteTasks.append(task)
    }