I have a FtpServerDataSeriesProvider
that is used to provide data series from Ftp server files:
public interface class FtpServerDataSeriesProvider
{
IEnumerable<DataSeries> GetDataSeries();
}
It has several concrete implementations that are specific to the company that owns the Ftp Server, like:
public class Company1FtpServerDataSeriesProvider : FtpServerDataSeriesProvider
{
public IEnumerable<DataSeries> GetDataSeries()
{
// code to extract data series from ftp server files
}
}
public class Company2FtpServerDataSeriesProvider : FtpServerDataSeriesProvider
{
public IEnumerable<DataSeries> GetDataSeries()
{
// code to extract data series from ftp server files
}
}
The data series extraction process itself is handled by a FileDataMiner
's which are used to extract data from specific file types content:
public interface IFileDataSeriesMiner
{
IEnumerable<DataSeries> GetDataSeries(byte [] fileContent);
}
GetDataSeries()
method parameter is a raw bytes array that presents the file content, inside this method it would be encoded / turn into MemoryStream
depending on the targer file type.
// To get data from CSV-based file
public abstract CsvFileDataSeriesMiner : IFileDataMiner
{
public abstract IEnumerable<DataSeries> GetDataSeries(byte [] fileContent);
// here might be some protected csv-related helper methods
}
// To get data from Xls-based file
public abstract XlsFileDataSeriesMiner : IFileDataMiner
{
public abstract IEnumerable<DataSeries> GetDataSeries(byte [] fileContent);
// here might be some protected xls-related helper methods
}
Then, there are also some concrete classes that represent different formats of input file data (each company stores data in different format):
public class Company1CsvFileDataSeriesMiner : CsvFileDataSeriesMiner
{
public IEnumerable<DataSeries> GetDataSeries(byte [] fileContent)
{
// do actual stuff
}
}
public class Company2CsvFileDataSeriesMiner : CsvFileDataSeriesMiner
{
public IEnumerable<DataSeries> GetDataSeries(byte [] fileContent)
{
// do actual stuff
}
}
public class Company1XlsFileDataSeriesMiner : XlsFileDataSeriesMiner
{
public IEnumerable<DataSeries> GetDataSeries(byte [] fileContent)
{
// do actual stuff
}
}
public class Company2XlsFileDataSeriesMiner : XlsFileDataSeriesMiner
{
public IEnumerable<DataSeries> GetDataSeries(byte [] fileContent)
{
// do actual stuff
}
}
Now, in order to able FtpServerDataSeriesProvider
to extract data from specific file format content, I need to pass / inject IFileDataSeriesMiner
somehow to the FtpServerDataSeriesProvider
concrete constructors.
But, it might be that on FtpServer there are Csv and Xls (and other) files present, so I need to be able to select proper IFileDataSeriesMiner dynamically within FtpServerDataSeriesProvider
code depending on the file format being currently processed.
So, my questions are:
- Should I inject a factory of
IFileDataSeriesMiner
intoCompany1FtpServerDataSeriesProvider
/Company2FtpServerDataSeriesProvider
constructors and then decide which miner object I need basing on e.g. file extension?
Miner's factory for Company1 would look like this:
public interface IFileDataSeriesMinerFactory
{
IFileDataSeriesMiner CreateMiner(string fileName);
}
public class Company1FileDataSeriesMinerFactory : IFileDataSeriesMinerFactory
{
// basing on file extension suitable Miner object is created
public static IFileDataSeriesMiner CreateMiner(string fileName);
}
public class Company1FtpServerDataSeriesProvider : FtpServerDataSeriesProvider
{
private IFileDataSeriesMinerFactory minerFactory;
public Company1FtpServerDataSeriesProvider(IFileDataSeriesMinerFactory minerFactory)
{
this.minerFactory = minerFactory;
}
// code ommited
}
- When there are several files that needs to be processed within server I would need to call the Miner's factory for every file that need processing, so for each of files new Miner object would be created - is that ok?
Simplified code for Company1FtpServerDataSeriesProvider:
public class Company1FtpServerDataSeriesProvider : FtpServerDataSeriesProvider
{
private IFileDataSeriesMinerFactory minerFactory;
public Company1FtpServerDataSeriesProvider(IFileDataSeriesMinerFactory minerFactory)
{
this.minerFactory = minerFactory;
}
public IEnumerable<DataSeries> GetDataSeries()
{
var ftpServerFilesToRead = ftpClient.GetFiles();
foreach (string filepath in ftpServerFilesToRead)
{
byte[] fileBytes = ftpRequest.DownloadData(filepath); // Read file bytes
var miner = minerFactory.CreateMiner(filename); // Create miner for current file to extract data series
foreach (var dataSeries in miner.GetDataSeries(fileBytes))
{
yield return dataSeries;
}
}
}
}