2012-03-06 2 views
7

J'utilise ce qui suit en ce moment:variables Utilisation à la place du nom de la fonction

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

Il fonctionne, mais il se sent un peu mal. La façon Python serait quelque chose comme ceci:

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

J'ai vraiment du mal à imaginer que C# ne peut pas faire quelque chose comme ça. Il se peut que mes compétences Google soient mauvaises, mais je n'arrive pas à le comprendre.

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

I suis désolé mais je ne suis pas capable de comprendre ce qui est filetype? –

+1

Pensez à définir les valeurs de commutateur enum au lieu de chaîne. Pas une solution à votre problème, mais une bonne pratique pour vous assurer d'attraper les erreurs compiler le temps. – Stilgar

+0

Montrez-nous comment vous obtenez/construisez '' fileType''. Peut-être un changement mineur là-bas (fournissant un délégué au lieu de chaîne) rend tout cela s'en aller facilement. –

Répondre

8

Vous pouvez le faire avec une certaine préparation à l'aide des délégués, comme ceci:

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

Quand il est temps d'appeler votre action , faites comme suit:

actionByType[actionName](file); 
+0

Python peut faire cela parce que c'est un langage dynamique. Même si C# prend en charge les types dynamiques, ce n'est pas un langage dynamique. C'est pourquoi vous devez utiliser quelque chose comme ça – linkerro

+0

J'aime ça mais je vois l'erreur: Erreur Argument '2': impossible de convertir 'groupe de méthodes' en 'System.Action ' – MTeck

+0

@MTeck Vos méthodes 'XYZFile (...)' ont-elles toutes la même signature? Est-ce qu'ils prennent 'RegularExpressions.Group'? Vos méthodes 'XYZFile (...)' sont-elles toutes statiques? – dasblinkenlight

4

Vous pouvez garder un Dictionary des délégués, comme la façon la plus simple:

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

Ensuite, appelez comme ceci:

fileReaders[fileType.Value](file); 

Selon ce que vos méthodes de retour, vous devrez peut-être pour changer le type du délégué (Action<string> signifie aussi void something(string someparam) comme signature de méthode, par exemple).

6

Vous pouvez utiliser un délégué:

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

Vous pouvez également utiliser la réflexion (si vous êtes d'accord avec les différents frais généraux qui peuvent apporter) Cocher cette solution

Espoir qui a aidé

2

Je crois que ce que vous cherchez aura besoin d'un refactoring de votre code. Tous vos «cas» (TextFile, MSOfficeWordFile, MSOfficeExcelFile, PdfFile) doivent être leurs propres classes qui implémentent une interface unique.

Votre interface doit s'appeler quelque chose comme "IReadableFile" et spécifier une méthode nommée "ReadFile()".

Chaque classe devrait avoir sa propre mise en œuvre de "ReadFile()"

Exemple:

public interface IReadableFile 
{ 
    void ReadFile(); 
} 

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

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

peut contenir des erreurs, mais je J'espère que vous avez l'idée.

0

Si vous êtes à la recherche d'un moyen d'éviter le mappage explicite des noms de méthode à des valeurs de chaîne, vous pouvez utiliser la réflexion pour faire appel de méthode dynamique (cela suppose filetype.Value est de 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}); 
} 
Questions connexes