I have been working on a program that reads data from various files and stores it into a common database table. The format of data in the files varies based on the data source, making each file unique. I need a way to determine the file reader based on the name of the data source, and I am having trouble avoiding a switch-case statement, even with an abstract factory in place. I know I could inject the IFileReader but that only pushes the switch-case up a level.
Below is an example of my current implementation. How can I completely eliminate the switch-case statement and still dynamically determine the file reader?
public class FileProcessor
{ 
    private readonly IFileReaderFactory _fileReaderFactory;
    private readonly FooDbContext _fooDb;
    public FileProcessor(IFileReaderFactory fileReaderFactory, FooDbContext fooDb)
    {
        _fileReaderFactory = fileReaderFactory;
        _fooDb = fooDb;
    }
    public void ProcessFile(string source, string filePath)
    {
        IFileReader fileReader;
        switch (source)
        {
            case "A":
                fileReader = _fileReaderFactory.CreateReader<FileReaderA>();
                break;
            case "B":
                fileReader = _fileReaderFactory.CreateReader<FileReaderB>();
                break;
            default:
                throw new Exception($"Unknown source: {source}");
        }
        _fooDb.Foos.AddRange(fileReader.ReadFile(filePath));
        _fooDb.SaveChanges();
    }
}
public interface IFileReaderFactory
{
    IFileReader CreateReader<T>() where T : IFileReader, new();
}
public class FileReaderFactory : IFileReaderFactory
{
    public IFileReader CreateReader<T>() where T : IFileReader, new()
    {
        return new T();
    }
}
public interface IFileReader
{
    List<Foo> ReadFile(string filePath); 
}
public class FileReaderA : IFileReader
{
    public List<Foo> ReadFile(string filePath)
    {
        // read file a
        return new List<Foo>();
    }
}
public class FileReaderB : IFileReader
{
    public List<Foo> ReadFile(string filePath)
    {
        // read file b
        return new List<Foo>();
    }
}
 
    