I am receiving an IFormFile from a controller. What I want to do next is to process it and get its content. I expect to get .docx, .txt or .pdf file and I want a single class to process any of these files based on extension given. I created and made my class to do it like that:
{
public static class DocumentProcessor // Should it be like this?
{
public static string GetContent(IFormFile file)
{
var result = new StringBuilder();
switch (Path.GetExtension(file.FileName))
{
case ".txt":
{
using(var reader = new StreamReader(file.OpenReadStream()))
{
while (reader.Peek() >= 0)
result.AppendLine(reader.ReadLine());
}
break;
}
}
return result.ToString();
}
}
}
Anyway, I feel like it is an extremely bad solution just because it is static. I could use the strategy pattern, but how do I define what strategy context has to use? Should I create another class that returns a Strategy object depending on IFormFile object extension. But I feel it is also a bad solution I would like to know what is the best way to solve this problem
CodePudding user response:
Create a new interface
interface IDocumentParser {
string GetContent(IFormFile file);
}
Implement that interface once per parser extension, e.g.:
class TextFileParser : IDocumentParser {
public string GetContent(IFormFile file) {
//your implementation code here
}
}
Then implement a factory:
class ParserFactory {
public static IDocumentParser GetParserForFilename(string filename) {
/*
This is the simple way. A more complex yet elegant way would be for all parsers to include a property exposing the filetypes it supports, and they are loaded through reflection or dependency injection.
*/
switch (Path.GetExtension(fileName))
{
case ".txt":
{
return new TextFileParser();
}
// add additional parsers here
}
return null;
}
}
And use:
IDocumentParser parser = ParserFactory.GetParserForFilename(file.FileName);
string content = parser.GetContent(file);
This is known as "Inversion of Control".