2012-03-06 67 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}); 
}