Making TaskCollection pass the stdout, stdin, stderr to Tasks they create. This allows for more flexible dependency injection and makes testing easier.
This will help reduce the coupling between ShellDispatcher and other objects.
Since ShellDispatcher never directly uses or interacts with TaskCollection, it doesn't make much sense for it to have one. Instead shells will either get their own, or be passed one in.