使用变量代替函数名称

时间:2012-03-06 15:02:00

标签: c# .net

我现在正在使用以下内容:

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;
    }
}

它有效,但感觉有点不对劲。 Python的方式更像是这样:

foreach string file in files:
    filetype.Value(file)

我很难想象C#不会做这样的事情。可能是我的Google技能不好,但我似乎无法弄明白。

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);
    }
}

6 个答案:

答案 0 :(得分:8)

您可以使用委托进行一些准备工作,如下所示:

private static readonly IDictionary<string,Action<string>> actionByType =
    new Dictionary<string,Action<string>> {
        {"ReadFile", ReadFile}
    ,   {"ReadMSOfficeWordFile", ReadMSOfficeWordFile}
    ,   {"ReadMSOfficeExcelFile", ReadMSOfficeExcelFile}
    ,   {"ReadPDFFile", ReadPDFFile}
    };

当需要调用您的操作时,请执行以下操作:

actionByType[actionName](file);

答案 1 :(得分:6)

您可以使用委托:

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);
}

答案 2 :(得分:4)

您可以保留Dictionary个代表,这是最简单的方法:

Dictionary<string, Action<string>> fileReaders = new Dictionary<string, Action<string>>() {
    {"ReadFile", ReadFile},
    {"ReadOfficeWordFile", ReadOfficeWordFile},
    {"ReadOfficeExcelFile", ReadOfficeExcelFile},
    {"ReadPDFFile", ReadPDFFile}
};

然后这样称呼:

fileReaders[fileType.Value](file);

根据您的方法返回的内容,您可能必须更改委托的类型(例如Action<string>表示void something(string someparam)作为方法签名)。

答案 3 :(得分:2)

我相信你所寻找的东西需要对你的代码进行一些重构。

所有“案例”(TextFile,MSOfficeWordFile,MSOfficeExcelFile,PdfFile)都应该是他们自己的实现单一界面的类。

您的界面应命名为“IReadableFile”,并指定名为“ReadFile()”的方法。

每个类都应该有自己的“ReadFile()”实现

示例:

public interface IReadableFile
{
    void ReadFile();
}

public class MSOfficeWordFile : IReadableFile
{
    public void ReadFile()
    {
        ReadMSOfficeWordFile(file);
    }
} 

foreach(IReadableFile file in files)
    file.ReadFile();

代码可能包含一些错误,但我希望你能理解。

答案 4 :(得分:1)

你也可以使用反射(如果你可以带来不同的开销) 请检查此solution

希望有所帮助

答案 5 :(得分:0)

如果您正在寻找避免将方法名显式映射到字符串值的方法,可以使用反射来进行动态方法调用(假设filetype.Value的类型为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});
}