You should avoid instancing classes in your UploadManager, and instead provide a UploaderFactory class which selects the specific uploader to use. To make this happen the Uploader and uploaderFactory need to implement interfaces (IUploader and IUploaderFactory). The factory has a method - GetUploader(...) which returns an instance of Uploader of the correct type.
No need for private classes - make it internal. The most important thing is to isolate functionality make everything testable.
So something like this:
interface IUploader
{
void DoStuff();
}
interface IUploaderFactory
{
IUploader GetUploader(UploadOperation uploadOperation);
}
internal class UploadManager
{
internal UploadManager(IUploaderFactory uploaderFactory, UploadOperation uploadOperation)
{
var uploader = uploaderFactory.GetUploader(uploadOperation);
//run different set of async tasks based on OperationType,
//using nested class Uploader
uploader.DoStuff();
}
}
internal class Uploader1 : IUploader
{
public void DoStuff()
{
...
}
}
internal class Uploader2 : IUploader
{
public void DoStuff()
{
...
}
}
internal class Uploader3 : IUploader
{
public void DoStuff()
{
...
}
}
The main benefits of this approach are:
- You can test each instance separatly. For instanace - you test the factory that it returns the correct Uploader, and in a whole different test-set you test the specific uploaders.
- You can easily add new uploaders with minimal change in code (only the new uploader and the factory needs to be modified. Oh, and the UploadOperation structure).
This is kind of vague answer, but I think it adresses the arcitecture approach.
Hope it helps - good luck!