Reputation: 1688
I'm using the following right now:
foreach (string file in files) {
switch (filetype.Value) {
case "ReadFile":
ReadFile(file);
break;
case "ReadMSOfficeWordFile":
ReadMSOfficeWordFile(file);
break;
case "ReadMSOfficeExcelFile":
ReadMSOfficeExcelFile(file);
break;
case "ReadPDFFile":
ReadPDFFile(file);
break;
}
}
It works, but it feels kinda wrong. The Python way would be something more like this:
foreach string file in files:
filetype.Value(file)
I have a really hard time imagining that C# can't do something like this. It may be that my Google skills are bad, but I can't seem to figure it out.
SOLUTION
public static readonly IDictionary<string, Action<string>> FileTypesDict = new Dictionary<string,Action<string>> {
{"*.txt", ReadFile},
{"*.doc", ReadMSOfficeWordFile},
{"*.docx", ReadMSOfficeWordFile},
{"*.xls", ReadMSOfficeExcelFile},
{"*.xlsx", ReadMSOfficeExcelFile},
{"*.pdf", ReadPDFFile},
};
foreach (KeyValuePair<string, Action<string>> filetype in FileTypesDict) {
string[] files = Directory.GetFiles(FilePath, filetype.Key, SearchOption.AllDirectories);
//System.Reflection.MethodInfo ReadFileMethod = ReadFile.GetType().GetMethod(filetype.Value);
foreach (string file in files) {
FileTypesDict[filetype.Key](file);
}
}
Upvotes: 7
Views: 8294
Reputation: 726559
You can do it with some preparation using delegates, like this:
private static readonly IDictionary<string,Action<string>> actionByType =
new Dictionary<string,Action<string>> {
{"ReadFile", ReadFile}
, {"ReadMSOfficeWordFile", ReadMSOfficeWordFile}
, {"ReadMSOfficeExcelFile", ReadMSOfficeExcelFile}
, {"ReadPDFFile", ReadPDFFile}
};
When it is time to call your action, do it as follows:
actionByType[actionName](file);
Upvotes: 9
Reputation: 4179
If you're looking for a way to avoid the explicit mapping of method names to string values you could use reflection to do dynamic method invocation (this assumes filetype.Value is of type String
)
String method_name = String.Empty;
foreach (string file in files) {
method_name = filetype.Value;
System.Reflection.MethodInfo method = this.GetType().GetMethod(method_name);
method.Invoke(this, new object[]{file});
}
Upvotes: 0
Reputation: 18142
I believe what you're looking for will need some refactoring of your code.
All of your "cases" (TextFile, MSOfficeWordFile, MSOfficeExcelFile, PdfFile) should be their own classes which implement a single interface.
Your interface should be named something like "IReadableFile" and specify a method named "ReadFile()".
Each class should have their own implementation of "ReadFile()"
Example:
public interface IReadableFile
{
void ReadFile();
}
public class MSOfficeWordFile : IReadableFile
{
public void ReadFile()
{
ReadMSOfficeWordFile(file);
}
}
foreach(IReadableFile file in files)
file.ReadFile();
Code may contain some mistakes, but I hope you get the idea.
Upvotes: 3
Reputation: 597
You could also use reflection (if you're okay with the different overhead that can bring) Check this solution
Hope that helped
Upvotes: 1
Reputation: 700312
You can use a delegate:
Action<string> action;
switch (filetype.Value) {
case "ReadFile":
action = ReadFile;
break;
case "ReadMSOfficeWordFile":
action = ReadMSOfficeWordFile;
break;
case "ReadMSOfficeExcelFile":
action = ReadMSOfficeExcelFile;
break;
case "ReadPDFFile":
action = ReadPDFFile;
break;
default:
throw new NotImplementedException("Unhandled file type '"+filetype.Value+"'.");
}
foreach (string file in files) {
action(file);
}
Upvotes: 6
Reputation: 224904
You could keep a Dictionary
of delegates, as the simplest way:
Dictionary<string, Action<string>> fileReaders = new Dictionary<string, Action<string>>() {
{"ReadFile", ReadFile},
{"ReadOfficeWordFile", ReadOfficeWordFile},
{"ReadOfficeExcelFile", ReadOfficeExcelFile},
{"ReadPDFFile", ReadPDFFile}
};
Then call it like this:
fileReaders[fileType.Value](file);
Depending on what your methods return, you may have to change the type of the delegate (Action<string>
means void something(string someparam)
as a method signature, for example) as well.
Upvotes: 4