2012-03-06 81 views
7

使用可變我現在使用如下:代替函數名

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技能不好,但我似乎無法弄清楚。

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

我很抱歉,但我無法弄清楚什麼是文件類型? – 2012-03-06 15:09:15

+1

考慮讓開關值枚舉而不是字符串。不是你的問題的解決方案,但一個很好的做法,以確保你編譯錯誤的時間。 – Stilgar 2012-03-06 15:12:06

+0

向我們展示您獲取/構造''fileType's的方式。可能在那裏做一個小改動(提供一個委託而不是字符串)使得它很容易消失。 – 2012-03-06 15:30:07

回答

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); 
+0

Python可以做到這一點,因爲它是一種動態語言。儘管c#支持動態類型,但它不是一種動態語言。這就是爲什麼你需要使用這樣的東西 – linkerro 2012-03-06 15:09:27

+0

我喜歡這個,但我看到的錯誤: 錯誤參數'2':無法從'方法組'轉換爲'System.Action ' – MTeck 2012-03-06 15:36:17

+0

@MTeck您的'XYZFile(...)'方法是否都具有相同的簽名?他們採取「RegularExpressions.Group」?你的'XYZFile(...)'方法也是靜態的嗎? – dasblinkenlight 2012-03-06 15:39:31

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)作爲方法簽名)。

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

您也可以使用反射(如果您能夠接受不同的開銷,這會帶來) 檢查這個solution

希望這有助於

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

代碼可能包含一些錯誤,但我希望你明白這個主意。

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