2012-03-06 18 views
7

Sto utilizzando il seguente in questo momento:Usa variabili al posto del nome della funzione

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

Funziona, ma ci si sente un pò male. Il modo in cui Python sarebbe qualcosa di più simile a questo:

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

ho un momento davvero difficile immaginare che C# non può fare una cosa del genere. Può darsi che le mie competenze su Google siano cattive, ma non riesco a capirlo.

SOLUZIONE

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 mi dispiace ma non sono in grado di capire cosa sia il tipo di file? –

+1

Considera di effettuare l'enum dei valori di commutazione anziché la stringa. Non è una soluzione al tuo problema, ma una buona pratica per assicurarti di raccogliere gli errori per compilare il tempo. – Stilgar

+0

Mostraci il modo in cui ottieni/costruisci '' fileType''s. Forse un cambiamento minore lì (fornire un delegato invece di una stringa) fa andare via tutto facilmente. –

risposta

8

Si può fare con un po 'di preparazione utilizzando i delegati, in questo modo:

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

Quando è il momento di chiamare la vostra azione , procedere come segue:

actionByType[actionName](file); 
+0

Python può farlo perché è un linguaggio dinamico. Anche se C# ha il supporto per i tipi dinamici, non è un linguaggio dinamico. Ecco perché è necessario utilizzare qualcosa come questo – linkerro

+0

Mi piace ma vedo l'errore: Errore Argomento '2': impossibile convertire da 'metodo gruppo' a 'System.Action ' – MTeck

+0

@MTeck I metodi 'XYZFile (...)' hanno tutti la stessa firma? Prendono "RegularExpressions.Group'? Inoltre, i metodi 'XYZFile (...)' sono tutti statici? – dasblinkenlight

4

si potrebbe tenere un Dictionary di delegati, come il modo più semplice:

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

Poi chiamare in questo modo:

fileReaders[fileType.Value](file); 

seconda di ciò che restituiscono i vostri metodi, si può avere per modificare il tipo di delegato (Action<string> significa anche void something(string someparam) come firma del metodo).

6

È possibile utilizzare un delegato:

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

È inoltre possibile utilizzare la riflessione (se stai bene con la testa diversa che può portare) Scegli questa solution

Speranza che ha aiutato

2

Credo che quello che stai cercando avrà bisogno di un refactoring del tuo codice.

Tutti i "casi" (TextFile, MSOfficeWordFile, MSOfficeExcelFile, PdfFile) devono essere classi proprie che implementano una singola interfaccia.

L'interfaccia deve essere denominata "IReadableFile" e specificare un metodo denominato "ReadFile()".

Ogni classe dovrebbe avere una propria implementazione di "ReadFile()"

Esempio:

public interface IReadableFile 
{ 
    void ReadFile(); 
} 

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

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

codice può contenere alcuni errori, ma io spero che tu abbia l'idea.

0

Se siete alla ricerca di un modo per evitare la mappatura esplicita dei nomi dei metodi ai valori di stringa si potrebbe usare la reflection per fare metodo dinamico invocazione (ciò presuppone filetype.Value è di tipo 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}); 
} 
Problemi correlati